EF Code First with One-to-Many and Many-to-Many relationships? cause cycles or multiple cascade paths - ef-code-first

I have four models that are Family, Mother, Father, Student, I am trying to associate Father& Mother& Student with Family table and Student table associated with Mother and Father tables. Here Family table contains information about the family. Mother and Father Tables contain their personal information, and Student table contains student information + MotherID and FatherID. Which means Family table was the Primary table to Mother and Father, Student table. MotherID of Mother table and FatherID of father table were referenced to Student table.
I am using MVC 4 Entity Framework Code First,
These are my model classes.
public class Family
{
public int FamilyID { get; set; }
public string FamilyName { get; set; }
public virtual ICollection<Mother> Mothers { get; set; }
public virtual ICollection<Father> Fathers { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Mother
{
public int MotherID { get; set; }
public int FamilyID { get; set; }
public string FirstName { get; set; }
public string SSN { get; set; }
public virtual Family Families { get; set; }
public virtual ICollection<Student> Students{ get; set; }
}
public class Father
{
public int FatherID { get; set; }
public int FamilyID { get; set; }
public string FirstName { get; set; }
public string SSN { get; set; }
public virtual Family Families { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int StudentID { get; set; }
public int FamilyID { get; set; }
public int MotherID { get; set; }
public int FatherID { get; set; }
public string FirstName { get; set; }
public string SSN { get; set; }
public virtual Family Families { get; set; }
public virtual Mother Mothers { get; set; }
public virtual Father Fathers { get; set; }
}
Database Context Class:
public class MYContext:DbContext
{
public DbSet<Family> Families { get; set; }
public DbSet<Mother> Mothers { get; set; }
public DbSet<Father> Fathers { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
//base.OnModelCreating(modelBuilder);
}
}
After writing the above code I just ran the below commands on package manager console.
PM> Add-Migration InitialContext It created an InitialContext.cs class for me.
PM> Update-Database -Verbose It give me an error below
Introducing FOREIGN KEY constraint 'FK_dbo.Student_dbo.Mother_MotherID' on table
'Student' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON
UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
What am I doing wrong??
Why I am getting this error??? Please help me some one!
What is the correct way to implement one-to-many and many-to-many relationships using EF code first? Please guide me with this example.

Try adding the [key] annotation immediately above your keys. For instance, for the student, it would look like this...
public class Student
{
[key]
public int StudentID { get; set; }
public int FamilyID { get; set; }
public int MotherID { get; set; }
public int FatherID { get; set; }
public string FirstName { get; set; }
public string SSN { get; set; }
public virtual Family Families { get; set; }
public virtual Mother Mothers { get; set; }
public virtual Father Fathers { get; set; }
}
This will tell you, in detail, how to manage your model from a codefirst perspective.
http://thedatafarm.com/blog/data-access/code-first-entity-framework-4-1-videos-and-articles-on-msdn/

I have found same problem and solution at Entity Framework, Code First modeling and a cyclical reference
The exception was coming from SQL Server DB not from entity framework, that table structure with the same constraints created by hand will be invalid. Foreign key properties of Mother table (Mother.FamilyID) and Father Table (Father.FamilyID), Student table (Student.MotherID) & (Student.FatherID) are not nullable, those representing required relationships and the corresponding columns in the database are also not nullable. So DB is not allowing this model.
If I remove all these properties from model classes then automatically relationship become optional because the navigation properties can be null, So DB treated as this is another model now since the FK columns in the DB can be nullable. Seemingly this is an allowed model.
It worked for me! Use nullable types as follows
Here is the solution for cause cycles or multiple cascade paths issues:
public class Student
{
public int StudentID { get; set; }
public int FamilyID { get; set; }
public int? MotherID { get; set; } //nullable types
public int? FatherID { get; set; } //nullable types
public string FirstName { get; set; }
public string SSN { get; set; }
public virtual Family Families { get; set; }
public virtual Mother Mothers { get; set; }
public virtual Father Fathers { get; set; }
}
Finally my model becomes with foreign key properties which represent optional instead of required relationship.
really very very thanks to # https://stackoverflow.com/users/270591/slauma and
https://stackoverflow.com/users/173937/decibyte for helping me in this type issue.

Related

ASP.NET Core Conflict with Foreign Key

I have got several models:
Course.cs
public class Course
{
public Guid Id { get; set; }
public ICollection<ApplicationUser> Teacher { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public DateTime CreationDate { get; set; }
public bool IsActive { get; set; }
}
Group.cs
public class Group
{
public Guid Id { get; set; }
public ApplicationUser Mentor { get; set;}
public string DisplayName { get; set; }
public string GroupName { get; set; }
public DateTime StartYear { get; set; }
public string InviteCode { get; set; }
public ICollection<ApplicationUser> Students { get; set; }
public ICollection<Course> Courses { get; set; }
}
ApplicationUser.cs
public class ApplicationUser : IdentityUser
{
[Required]
public string Firstname { get; set; }
[Required]
public string Surname { get; set; }
public bool Gender { get; set; }
public DateTime Birthdate { get; set; }
//[Required]
public string InviteCode { get; set; }
public Guid GroupId { get; set; }
[ForeignKey("GroupId")]
public Group CurrentGroup { get; set; }
public ICollection<Group> PastGroups { get; set; }
}
Now when I try to register (using Identity) a user (not even trying to give the user a group) I receive this error:
SqlException: The INSERT statement conflicted with the FOREIGN KEY
constraint "FK_AspNetUsers_Groups_GroupId". The conflict occurred in
database "aspnet-Project_Dojo-3af15f80-8c62-40a6-9850-ee7a296d0726",
table "dbo.Groups", column 'Id'. The statement has been terminated.
In my modelBuilder I have added some logics for the relations between Group, ApplicationUser (Students) and the Foreign Key:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);\\
builder.Entity<ApplicationUser>()
.HasOne(p => p.CurrentGroup)
.WithMany(b => b.Students)
.HasForeignKey(p => p.GroupId);
}
I don't know what this is exactly doing, but I've been browsing some Stackoverflow threads to come to this code (migrations weren't working without it).
I look forward to a solution for my problem. Once again, I'm not doing ANYTHING with the groups yet when registering.
Thanks in advance!
not even trying to give the user a group
Well there's your problem, it's required.
Either provide a group, or make it optional by making the foreign key nullable (Guid? GroupId).
Because it's currently a non-nullable struct, it'll have a default value of all zeroes (Guid.Empty). This FK is not known in your database, resulting in the error you see.

Add a column to a many to many relation table code first entity framework

I have 2 classes which have a many to many relation.
public class Document
{
public int Id { get; set; }
public string Name { get; set; }
public bool AvailableOffline { get; set; }
public string URL { get; set; }
public virtual ICollection<Profile> Profiles { get; set; }
}
public class Profile
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Document> Documents { get; set; }
}
On each profile I wish to have a SortOrder field for each document. So I made the joined table explicit in another class
public class ProfileDocuments
{
[Key, Column(Order = 0)]
public int DocumentId { get; set; }
[Key, Column(Order = 1)]
public int ProfileId { get; set; }
public int SortOrder { get; set; }
[ForeignKey("DocumentId")]
public virtual Document Document { get; set; }
[ForeignKey("ProfileId")]
public virtual Profile Profile { get; set; }
}
But when I update the database the table for this last class will not have a column for SortOrder. It only holds the 2 foreign keys. How can I tell EF to generate this table with my column?
When a junction table in a many-to-many association should contain more information than just the two foreign keys, it's no longer possible to map the association as a 'pure' many-to-many (with hidden junction class).
You need an explicit class in the class model to address the extra information (as you already found out), but this also changes the association into 1-n-1:
class Document
{
...
public virtual ICollection<ProfileDocument> ProfileDocuments { get; set; }
}
class Profile
{
...
public virtual ICollection<ProfileDocument> ProfileDocuments { get; set; }
}

Navigation property from dependent to principal

I have two Entities
public class Person
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual Employee Employee { get; set; }
}
public class Employee
{
public virtual int ID { get; set; }
public virtual string Code { get; set; }
public virtual int PersonId { get; set; }
[ForeignKey("PersonId")]
public virtual Person Person { get; set; }
}
in my business first we create person then we create an employee by selecting a person, while selecting person for the employee i want to select only the persons who are not associated to employee, i couldn't figure how to configure the Employee property in Person Entity
If you are selecting people that aren't related to a specific employee then you shouldn't have a property for that. You should only have link to related entities. Try doing this in LINQ it should get you all people that don't have a relation to an employee.
var people = context.People.Where(x => x.Employee == null);
public class Person
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual Employee Employee { get; set; }
}
public class Employee
{
public virtual int ID { get; set; }
public virtual string Code { get; set; }
public virtual int PersonId { get; set; }
[ForeignKey("PersonId")]
[InverseProperty("Employee")]
public virtual Person Person { get; set; }
}
Think that should do it, inverse property creates the mapping so only needs to be done from one side.
Hope this is what you were looking for.
I figured out an answer, don't know if it's the best!
jobQuery = jobQuery.Where(jb => !Context.Employees.Any(emp => emp.JobId == jb.Id));

Parent and child record added on single MVC View

In ASP.NET MVC 5 and EF6 Code First, i have a case in which a student can have one to many addresses. Now i want to use Student model in View to add both the record Student and Addresses of student. But the problem is i cant add addresses of student, is there any appropriate solution for this solution
Here is the example code
public class Student
{
public Student()
{ }
[Key]
public int StudentID { get; set; }
[Required]
public string Name { get; set; }
public virtual List<Address> Address { get; set; }
}
public class Address
{
public Address()
{
}
[Key]
public int AddressID { get; set; }
[ForeignKey("Student")]
public int StudentID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string PostalCode { get; set; }
public string State { get; set; }
public string City { get; set; }
public string Country { get; set; }
public virtual Student Student { get; set; }
}
Make Listbox for address's and Pass with List that will be really help you and can you paste controller code here?

How do I build a class that shares a table with multiple columns in MVC3?

I have a Job table
public class Job
{
public int JobId { get; set; }
public int SalesManagerId { get; set; }
public int SalesRepId { get; set; }
}
and a Person table
public class Person
{
public int PersonId { get; set; }
public int FirstName { get; set; }
public int LastName { get; set; }
}
My question is, how do I link the SalesManagerId to the Person (or PersonId) as well as the SalesRepId to the Person (PersonId)? The Sales Manager and Sales Rep are independent of each other. I just don't want to make 2 different lists to support the Sales Manager and Sales Rep roles.
I'm new to MVC3, but it seems public virtual Person Person {get; set; } would be the way to go, but that doesn't work.
Any help would be appreciated!
Thanks!
Change your Job class like this
public class Job
{
public int JobId { get; set; }
public virtual Person SalesManager { set; get; }
public virtual Person SalesRep { set; get; }
}
This will create the Job table with 3 columns. JobId, SalesManager_PersonID (ForiegnKey) ,SalesRep_PersonID (Foriegn key)

Resources