Entity relationship not working - asp.net-mvc

public class Slider_Locale
{
[Key]
public int Slider_LocaleID { get; set; }
[ForeignKey("Culture")]
public int CultureID { get; set; }
public string Slogan { get; set; }
public virtual Culture Culture { get; set; }
}
public class Culture
{
[Key]
public int CultureID { get; set; }
public string CultureName { get; set; }
public string DisplayName { get; set; }
public virtual Slider_Locale slider_Locale { get; set; }
}
It gives error as follows:
One or more validation errors were detected during model generation:
System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role
'Slider_Locale_Culture_Source' in relationship
'Slider_Locale_Culture'. Because the Dependent Role properties are not
the key properties, the upper bound of the multiplicity of the
Dependent Role must be �*�.
How could I design the relationship?. Please help me as I am newbie in mvc and entity.

This is one of those things that's a little tricky to wrap your brain around at first. The issue is that you're trying to set up a 1:1 (or 1:0) mapping, but there's nothing in your model to enforce that kind of mapping. For example, what if you have more than one Slider_Locale object with the same CultureID value? How would your application know which one to pick?
Now, you might know that this will never happen, but the Entity Framework doesn't, and it has to err on the side of caution, so it won't let you set up a relationship that it can't prove is consistent with the table structure. Ideally, it would let you specify unique constraints other than a primary key to work around this, and maybe someday it will, but for now the simplest way around this is to change it to a one-to-many mapping. For example, you could do:
public class Slider_Locale
{
[Key]
public int Slider_LocaleID { get; set; }
[ForeignKey("Culture")]
public int CultureID { get; set; }
public string Slogan { get; set; }
public virtual Culture Culture { get; set; }
}
public class Culture
{
[Key]
public int CultureID { get; set; }
public string CultureName { get; set; }
public string DisplayName { get; set; }
// Note that this got changed to ICollection<>
public virtual ICollection<Slider_Locale> slider_Locales { get; set; }
}
Another thing you could do is change the classes so that they share the same primary key values, but in order to do that you'll have to make at least one of the relationships optional. I could give an example of this if you let me know whether Slider_Locale.Culture can be null, or Culture.slider_Locale, or both.

Related

Entity Framework 6 and Chained Relationships

Having some issues with relationships within EntityFramework 6.
I know that DataAnnotations or FluentApi can be used and I'm okay with using either.
Here's an example of relationship I'd like to accomplish:
Student has one ImmunizationRecord
ImmunizationRecord has Multiple ShotRecords
This seems like it would be fairly straight forward, however it doesn't seem to be working as expected.
Here's example code (Updated from actual code)
public class Student : Entity
{
[Key]
public int Id { get; set; }
public String Name { get; set; }
//...
[ForeignKey(nameof(Id))]
public virtual ImmunizationRecord ImmunizationRecord { get; set; }
}
public class ImmunizationRecord : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Key]
[ForeignKey(nameof(Student))]
public int StudentId { get; set; }
public String Name { get; set; }
public DateTime LastUpdated { get; set; }
public virtual Student Student { get; set; }
public virtual ICollection<ShotRecord> ShotRecords { get; set; }
}
public class ShotRecord: Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// Want this to point back to ImmunizationRecord
public int ImmunizationRecordId { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public DateTime DateOfShot { get; set; }
//...
[ForeignKey("ImmunizationRecordId")]
public virtual ImmunizationRecord ImmunizationRecord { get; set; }
}
Example fluentapi might be something like this:
modelBuilder.Entity<Student>().HasOptional(c => c.ImmunizationRecord).WithRequired(m => m.Student);
modelBuilder.Entity<Student>().HasOptional(c => c.ImmunizationRecord).WithRequired(sc => sc.Student);
modelBuilder.Entity<ImmunizationRecord>().HasMany(sc => sc.ShotRecords).WithRequired(sr => sr.ImmunizationRecord);
The Result
I suspect that I'm just missing a small piece of what needs to be done, or missing the proper way to configure these entities with a similar relationship.
With the code above and class structure, I can create a Student, and Create a ImmunizationRecord, and ShotRecords without issue.
The issue occurs when I try to retrieve the ShotRecords from The ImmunizationRecord, EntityFramework will resolve on the key on the Student.Id instead of using the key of on the ImmunizationRecord.Id.
I can go into the database and change the rows for ShotRecords and update the ImmunizationRecordId to the StudentId and they'll resolve properly. But as stated before, I want them to use the key of the ImmunizationRecord, and not the student.
Any advice and guidance would be greatly appreciated!
Thank you in advance!
(Updated to a different example to make more sense)

Two optional one-to-one EF relationship

Is it possible to build two optional one-to-one relationship in SQL?
I'd like to have:
public class EventInvoice
{
[Key]
public int ID { get; set; }
[ForeignKey("SZ_Event")]
public Nullable<int> SZ_EventID { get; set; }
public virtual SzopbudkaEvent SZ_Event { get; set; }
[ForeignKey("UP_Event")]
public Nullable<int> UP_EventID { get; set; }
public virtual Event UP_Event { get; set; }
}
public class Event
{
[Key]
public int EventID { get; set; }
public virtual EventInvoice EventInvoice { get; set; }
}
public class SzopbudkaEvent
{
[Key]
public int ID { get; set; }
public virtual EventInvoice EventInvoice { get; set; }
}
My invoice can be combined only with one of those objects (Event or SzopbudkaEvent). Is it possible to use it like this or I have to write something different?
You can do this but there are two things to bear in mond.
If the constraint is only one of the FK's can exist, then in the database the FK columns on the EventInvoice tale must be nullable. You've got this but I thought I'd emphasise it.
If there is also a constraint that there must be one of them (missing both is not allowed) then you have to work out how to validate that constraint. In the DB I'd use a trigger fir insert, update that raises an exception if both are null. I'd match that in code with a pre-save check: this describes implementing interface IValidatableObject with a Validate method which EF will call when the object is affected by SaveChanges.

Validation error during model generation in one-to-many relationship

When I run application I have this error:
PossibleAnswer_Question_Source: : Multiplicity is not valid in Role
'PossibleAnswer_Question_Source' in relationship
'PossibleAnswer_Question'. Because the Dependent Role properties are
not the key properties, the upper bound of the multiplicity of the
Dependent Role must be '*'.
How to resolve it?
Model classes for Question and PossibleAnswer:
public class Question
{
public int ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public virtual ICollection<PossibleAnswer> PossibleAnswers { get; set; }
}
public class PossibleAnswer
{
public int ID { get; set; }
public string Text { get; set; }
public int QuestionID { get; set; }
[ForeignKey("QuestionID")]
public virtual Question Question { get; set; }
}
And I put this in OnModelCreating(DbModelBuilder modelBuilder):
modelBuilder.Entity<PossibleAnswer>()
.HasRequired(f => f.Question)
.WithRequiredDependent()
.WillCascadeOnDelete(false);
The problem is you are not configuring a one-to-many relationship in the OnModelCreating method (that is a one-to-one configuration). To achieve what you want, you could do this:
modelBuilder.Entity<PossibleAnswer>()
.HasRequired(pa => pa.Question)
.WithMany(q=>q.PossibleAnswers)
.HasForeignKey(pa=>pa.QuestionID)
.WillCascadeOnDelete(false);
This way, you don't need to use the ForeignKey attribute on the Question navigation property. Is a good practice try to not merge Fluent Api with Data Annotations

ASP.NET MVC 3 EF Code First - How do I make a model that optionally refers to a parent of its own type?

I'm trying to create a model that can optionally refer to a parent of the same type, for example:
public class Category
{
public virtual long CategoryID { get; set; }
public virtual Category? ParentCategory { get; set; }
public virtual int UserID { get; set; }
public virtual string Name { get; set; }
}
As you can see there is an optional member called ParentCategory that is optional and refers to a class of type Category (i.e. the same type). As I'm sure you can guess, I'm trying to create a simple Category tree, where the root node(s) will not have a parent.
This results in the following error when the Entity Framework tries to create the database:
"The ForeignKeyAttribute on property 'ParentCategoryID' on type 'MyProject.Models.Category' is not valid. The navigation property 'Category' was not found on the dependent type 'MyProject.Models.Category'. The Name value should be a valid navigation property name."
I also tried this:
public class Category
{
public virtual long CategoryID { get; set; }
[ForeignKey("Category")]
public virtual long? ParentCategoryID { get; set; }
public virtual int UserID { get; set; }
public virtual string Name { get; set; }
}
But again this resulted in the same error.
Is it possible to model this using EF Code First? Its easy to model it int he database if I were to create the database manually.
Thanks in advance
Ben
Your first example wouldn't even compile because T?, a shortcut for Nullable<T> can only be applied to value types.
The following works fine here:
public class Category
{
public virtual long CategoryID { get; set; }
public virtual Category ParentCategory { get; set; }
}
Now, this will use an ugly name by default for the FK, ParentCategory_CategoryID.
This is a way to get a nicer name, plus some flexibility when using it:
public class Category
{
public virtual long CategoryID { get; set; }
[ForeignKey("ParentCategoryID")]
public virtual Category ParentCategory { get; set; }
public virtual long? ParentCategoryID { get; set; }
}

EF CTP4: How to tell EF a column is NOT identity

I have a code-first, POCO project in which I am trying to adjust an existing database so that it syncs up with what EF is expecting, given my existing model.
I have these entities:
public class FlaggedDate
{
[Key]
public long scheduledDayID { get; set; }
[Required]
public DateTime date { get; set; }
[StringLength(50)]
[Required]
public string dateStatus { get; set; }
[Required]
public bool isVisit { get; set; }
[Required]
public bool hasAvailableSlots { get; set; }
[Required]
public bool hasInterviewsScheduled { get; set; }
// navigation properties
public ICollection<ScheduledSchool> scheduledSchool { get; set; }
public ICollection<Interview> interviews { get; set; }
public ICollection<PartialDayAvailableBlock> partialDayAvailableBlocks { get; set; }
public Visit visit { get; set; }
public ICollection<Event> events { get; set; }
}
and
public class Visit
{
[Key]
public long flaggedDateScheduledDayID { get; set; }
[Required]
public bool isFullDay { get; set; }
// navigation property
public FlaggedDate flaggedDate { get; set; }
}
The relationship between these two is 1 : 0|1 -- i.e., FlaggedDate will exist but it may or may not have a corresponding single Visit object.
EF thinks, based on this model, that FlaggedDate should have an extra field, visit_flaggedDateScheduledDayID, which is nullable. I finally realized why: it thinks the Visit field, flaggedDateScheduledDayID, is an identity column. It's not supposed to be an identity column; it's supposed to be a foreign key that connects to FlaggedDate.
I think it does this by convention: I remember reading something to the effect that in CTP4, any field that is a single key and is int or long is assumed to be an identity column.
Is there any way I can tell EF that this is NOT an identity column? I tried fiddling with the Fluent API, but it's a mystery to me, and there are no data annotations that you can use for this.
Or, alternatively, is there any way I can fiddle with the navigation properties to get this to come out right?
If you're using mapping files with fluent API
this.Property(t => t.Id)
.HasColumnName("Site_ID")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
I would imagine it should also work declaratively
[HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)]
although I didn't try that.
I discovered I can override the identity behavior with this code:
modelBuilder.Entity<Visit>().Property(v => v.flaggedDateScheduledDayID).StoreGeneratedPattern = System.Data.Metadata.Edm.StoreGeneratedPattern.None;
However, it is still not making it a foreign key. I guess that's a different question, though. It seems setting the StoreGeneratedPattern to None is the way to override the default behavior.

Resources