Entity Framework Cascade Delete Error - entity-framework

I'm learning EF, and have an error when trying to create my database. Introducing FOREIGN KEY constraint 'FK_dbo.ApplicationUserBuildings_dbo.Buildings_Building_BuildingID' on table 'ApplicationUserBuildings' 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 or index. See previous errors.
I understand what this error means, but I don't know exactly what do to in my code to get rid of if. I believe it's because there's a relationship between users and buildings and divisions and buildings. Here's my code. Users can have multiple buildings, Divisions can also have multiple buildings.
public class Division : Common.BaseModel
{
[Required]
[Key]
public int DivisionID { get; set; }
[Required]
public String Name { get; set; }
public virtual ICollection<Building> Buildings { get; set; }
}
public class Building : Common.BaseModel
{
[Required]
[Key]
public int BuildingID { get; set; }
[Required]
public String Name { get; set; }
public int DivisionID { get; set; }
public virtual Division Division { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUsers { get; set; }
}
public class ApplicationUser
{
public virtual ICollection<Building> Buildings { get; set; }
public int DivisionID { get; set; }
public virtual Division Divison { get; set; }
}

Related

FOREIGN KEY constraint May cause cycles or multiple paths

I have read tons of articles seemingly similar to my issue, but just haven't been able to arrive at my ideal solution.
My specific error says:
Introducing FOREIGN KEY constraint 'FK_Scores_Tees_TeeId' on table 'Scores' may cause cycles or multiple cascade paths.
So, the table in question here, looks like this:
{
[Key]
public Guid ScoreId { get; set; }
public int Strokes { get; set; }
public Guid PersonId { get; set; }
public Guid CourseId { get; set; }
public Guid TeeId { get; set; }
[ForeignKey("PersonId")]
public virtual Person Person { get; set; }
[ForeignKey("CourseId")]
public virtual Course Course { get; set; }
[ForeignKey("TeeId")]
public virtual Tee Tee { get; set; }
}
Now, this table references Tees table, shown here:
public class Tee
{
[Key]
public Guid TeeId { get; set; }
public string Name { get; set; }
public int Par { get; set; }
public int Yards { get; set; }
public float Rating { get; set; }
public int Slope { get; set; }
public Guid CourseId { get; set; }
[ForeignKey("CourseId")]
public virtual Course Course { get; set; }
}
I read about making the TeeId nullable in the Scores table. I did that and was able to build run my migration successfully... however I do need this field to be required. If that id is empty/null then I don't have enough information about that particular Score record.
Both Tee and Score have a required reference to Course. When you delete a referenced Course, EF will want to delete the associated Tee and Score. When Tee is deleted, EF will again want to delete the associated Score. This is the "multiple cascade path" problem.
This error brings to light a problem with the design; the two references to Course can be different values which makes no sense in the context used (the score is for one course while referencing a "tee" from another course?). You should refactor your design.
Tees in golf are usually a small subset of value by either color (blue, white, gold, red) or name (ladies', back/champions', seniors, etc). One way to resolve your design issue is to normalize these name and/or color values in a Tee table, then have a CourseTee table that defines the properties of the Course's tees. This would be done by using a compound key either as primary key or candidate key (called alternate key in EF) composed of FK's to Course and Tee. This entity is where you would then define the properties of the course's tees:
public class CourseTee
{
[Key]
public Guid CourseId { get; set; }
public Course Course { get; set; ]
[Key]
public Guid TeeId { get; set; }
public Tee Tee { get; set; }
public int Par { get; set; }
// additional course-tee specific properties
...
}
public class Score // as a golfer, change this to `Round`
{
[Key]
public Guid ScoreId { get; set; } // RoundId :D
public Person Player { get; set; }
public CourseTee CourseTee { get; set; }
public int Strokes { get; set; }
...
}
public class Tee
{
public Guid TeeId { get; set; }
public string Color { get; set }
public string Name { get; set; }
}
Now Course is only defined once in a Score's object graph. To get the Course for a given Score is simply an extra hop: score.CourseTee.Course

Entity Framework and Introducing FOREIGN KEY constraint error in many-to-many relationship

I'm trying to create next model for a web app:
A company can create customers and categories (for customers).
A customer can belong to several categories.
Several customers can belong to the same category.
Entities:
public class Company
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Customer> Customers { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Customer
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int CompanyId { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int CompanyId { get; set; }
[Required]
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<Customer> Customers { get; set; }
}
Data context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Company> Companies { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Customer> Customer { get; set; }
public ApplicationDbContext()
: base(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString, throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
When I run the app and try to get a company, I get the next error:
Introducing FOREIGN KEY constraint 'FK_dbo.CustomerCategories_dbo.Categories_Category_Id' on table 'CustomerCategories' 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 or index. See previous errors.
I don't understand why I getting this error. I think it is a many-to-many relationship which is the problem. What am I doing wrong?

EF 6 cycles or multiple cascade paths

I'm trying to create my database from my models, but I keep getting the error Introducing FOREIGN KEY constraint 'FK_dbo.Reports_dbo.UserProfiles_UserId' on table 'Reports' 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.
anyone knows what might be wrong with my models/setup?
These are all used Models
public class Report {
[Key]
public int Id { get; set; }
[Required]
public string Number { get; set; }
public bool Synced { get; set; }
public DateTime CreationDate { get; set; }
public int NewCommentId { get; set; }
public virtual Comment NewComment { get; set; }
public int UserId { get; set; }
public virtual UserProfile User { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Photo> PhotosBefore { get; set; }
public virtual ICollection<Photo> PhotosAfter { get; set; }
}
public class Photo {
[Key]
public int Id { get; set; }
public string Image { get; set; }
public bool Synced { get; set; }
public DateTime CreationDate { get; set; }
public int ReportId { get; set; }
public virtual Report Report { get; set; }
public int UserId { get; set; }
public virtual UserProfile User { get; set; }
}
public class Comment {
[Key]
public int Id { get; set; }
public DateTime CreationDate { get; set; }
public string Text { get; set; }
public int ReportId { get; set; }
public virtual Report Report { get; set; }
public int UserId { get; set; }
public virtual UserProfile User { get; set; }
}
public class UserProfile {
[Key]
public int Id { get; set; }
public string Stamnummer { get; set; }
public string Leverancier { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Report> Reports { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
In order to be certain, we need to see how you have configured your relationships using the model builder in the OnModelCreating method. Based on the error message you have provided, it appears that you have relationships configured so that one of your entities is configured for cascade on delete from two or more other entities.
As an example (this may not be the case, but rather just a means of describing the problem):
User has a one-to-many relationship with Comments
User has a one-to-many relationship with Reports
Report has a one-to-many relationship with Comments
Comment is configured so that a User is required
Comment is configured so that a Report is required
Report is configured so that a User is required
Any one-to-many relationship where the entity one side of the relationship is required is going to have cascade on delete configured by default. In this scenario, if a User were deleted it would trigger a cascade to both Reports and Comments. Each Report would also cause a cascade on Comments.
The solution is to disable cascading deletes for one of the relationships. You can find a similar question to yours here describing what I mentioned above.

EF Code first : set optional one to one relationship with data annotation

I've the following situation I try to solve : I've 2 tables, a Course table with some fields and a CourseDescription table which is optional (so Course may have a CourseDescription but CourseDescription must have a Course). I'm trying to set this up. So far, here's what I have :
public class Course
{
[Key, Column("Key_Course")]
public int ID { get; set; }
public string Name { get; set; }
public virtual CourseDescription CourseDescription { get; set; }
}
public class CourseDescription
{
[Key, ForeignKey("Course")]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
public int CoursesID { get; set; }
[ForeignKey("CoursesID")]
public Course Course { get; set; }
}
This "works" meaning that EF doesn't complains about my model but the relation is not properly done because EF associate the PK of CourseDescription with the PK of Course. In my database, this is not the case (ex : CourseDescription.ID=1 is associated with CourseDescription.CoursesID=3, not 1).
Is there a way to fix that with data annotation ? I know I can use the fluent API but I don't want to override the model building just for that (unless there's no other way).
Thanks
Well, I think you have two choices:
Configure an one to many relationship
If you want to map the FK of the relationship between Course and CourseDescription, and you don't want to declare that FK property as Key of the CourseDescription entity, then, you don't have other choice that configure an one-to-many relationship. In that case your model would be like this:
public class Course
{
[Key, Column("Key_Course")]
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<CourseDescription> CourseDescriptions { get; set;}
}
public class CourseDescription
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
[ForeignKey("Course")]
public int CourseID { get; set; }
public Course Course { get; set; }
}
Configure an one-to-one relationship but not map the FK of the
relationship
The only way that EF lets you map the FK in an one-to-one relationship is when the FK is declared as a PK too, so if you want to have diferent Ids in both entities and you want to stablish an one-to-one relationship, then you could do something like this:
public class Course
{
[Key, Column("Key_Course")]
public int ID { get; set; }
public string Name { get; set; }
public CourseDescription CourseDescription { get; set;}
}
public class CourseDescription
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
[Required]
public Course Course { get; set; }
}
And work with the navigations properties.
It looks like you should not use ForeignKey attribute for ID property of CourseDescription class as you don't want to have an association between primary keys. Try to remove it.
Edit: It looks like I misunderstood the question previous time.
You can have your CourseDescription this way.
public class CourseDescription
{
[Key, ForeignKey("Course")]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
public Course Course { get; set; }
}
In this case you don't need to have CoursesID field. Entities will be connected by primary keys.

EF6 Foreign Key Issue

Here are my models
public class Driver
{
public int Id { get; set; }
public String Name { get; set; }
public int VehicleId { get; set; }
public virtual Vehicle Vehicle { get; set; }
}
public class Vehicle
{
public int Id { get; set; }
public String Name { get; set; }
public virtual Driver Driver { get; set; }
public int VehicleGroupId { get; set; }
public virtual VehicleGroup Vehicles { get; set; }
}
I'm getting the following error on updating database:
Unable to determine the principal end of an association between the types 'AppName.Models.Vehicle' and 'AppName.Models.Driver'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I wish to solve the issue using data annotations. I've tried putting foreign key attribute over Driver Navigation property in vehicle model. But no success. Any help is much appreciated.
To solve your problem you need to explicitly set the end of the association like this :
public class Vehicle
{
[Key, ForeignKey("Driver")]
public int Id { get; set; }
public String Name { get; set; }
public virtual Driver Driver { get; set; }
public int VehicleGroupId { get; set; }
public virtual VehicleGroup Vehicles { get; set; }
}
I think your model is inccorect because a driver can use many vehicles in real life ;)