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.
Related
I'm trying to set the Model builder cascade property but I'm not getting the syntax correct.
Simple database:
I have a class (ReqForBetaReader):
public class ReqForBetaReader
{
public ReqForBetaReader()
{
Tags = new List<TagForReqBeta>();
}
public Guid Id { get; set; }
public string Title { get; set; }
public string Synopsis { get; set; }
public int WordCount { get; set; }
public Guid AuthorId { get; set; }
public virtual User Author { get; set; }
public DateTime UpdatedOn { get; set; }
public virtual ICollection<TagForReqBeta> Tags { get; set; }
}
I have my TagForReqBeta class
public class TagForReqBeta
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public Guid ReqForBetaReaderId { get; set; }
public virtual ReqForBetaReader ReqForBetaReader { get; set; }
[Required]
public Guid UserId { get; set; }
public virtual User User { get; set; }
public DateTime AddedOn { get; set; }
}
So a ReqForBeta can have multiple tags.
When I ran Update-Database, I got the dreaded:
Introducing FOREIGN KEY constraint 'FK_TagsOnRequestForBetaReaders_RequestsForBetaReaders_ReqForBetaReaderId' on table 'TagsOnRequestForBetaReaders' 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 believe this means that when I delete a ReqForBeta, I should also delete all the TagForReqBeta as well, but I'm having trouble with the syntax. Any help?
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<ReqForBetaReader>()
.HasMany<TagForReqBeta>(x => x.Tags)
.WithOne<ReqForBetaReader>(x => x.ReqForBetaReaderId)
.OnDelete(DeleteBehavior.Cascade);
base.OnModelCreating(builder);
}
Since ReqForBetaReaderId is not nullable, when you delete ReqForBetaReader record you will have to delete TagForReqBeta.
Since as I understand the same tag can be used for several records you have to make ReqForBetaReaderId nullable
[Required]
public Guid? ReqForBetaReaderId { get; set; }
builder.Entity<ReqForBetaReader>()
.HasMany<TagForReqBeta>(x => x.Tags)
.WithOne<ReqForBetaReader>(x => x.ReqForBetaReaderId)
.OnDelete(DeleteBehavior.ClientSetNull);
and as #IvanStoev noticed you have the same problem with User
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; }
}
I Got This Issue:
I Have the Application User Class Like This
public class ApplicationUser : IdentityUser
{
public ROLES Role { get; set; }
public int? CompanyId { get; set; }
public int? AreaId { get; set; }
public string Document { get; set; }
public bool Enable { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[ForeignKey("AreaId")]
public virtual Area Area { get; set; }
public virtual ICollection Measures { get; set; }
}
And I Got this another Model:
public class Area
{
public int AreaId { get; set; }
public string AreaName { get; set; }
public int CompanyId { get; set; }
public string UserId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[Key, ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
}
And when i try to:
add-migration
the PM Console throws:
Unable to determine the principal end of an association between the types 'x.Models.ApplicationUser' and 'x.Models.Area'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I have been trying all day but I can't find a way to tell the Entity Framework to recognize the relation.
Any ideas?
Thanks for reading
Add Attribute for AreaId in Area class
[Key]
public int AreaId { get; set; }
and if you want 1-1 relationship for ApplicationUser and Area update your code like
[Unique]
[ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations
This Post give me the Answer I Need!!!
It's pretty hard to find...
So I let you the post here...
Thanks for all of your help!
I have a Holiday table and a User table.
The Holiday table has columns RequesterID and AuthorisedByID, which both link to the primary key of the User table.
This is my Holiday model:
public class Holiday
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid HolidayId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public Guid RequesterId { get; set; }
public Guid? AuthorisedById { get; set; }
}
I am unable to declare the AuthorisedByID as a foreign key in the User table just like I think I did with RequesterId column.
I wonder if you can give me some hints on how to resolve.
Thanks.
Code first is not able to match up the properties in the two classes on its own.
To fix these problems, you can use the InverseProperty annotation to specify the alignment of the properties.
[ForeignKey("RequesterUser")]
public Guid RequesterId { get; set; }
[ForeignKey("AuthorisedUser")]
public Guid AuthorisedById { get; set; }
[InverseProperty("RequesterHoliday")]
public virtual User RequesterUser{ get; set; }
[InverseProperty("AuthorisedHoliday")]
public virtual User AuthorisedUser{ get; set; }
public List<Holiday> RequesterHoliday { get; set; }
public List<Holiday> AuthorisedHoliday{ get; set; }
I have the following model:
public class Job
{
[Key]
public int JobId { get; set; }
public string Description { get; set; }
public DateTime DateCreated { get; set; }
public DateTime? DueDate { get; set; }
public int JobIdentity { get; set; }
[MaxLength(50, ErrorMessage = "Please ensure the Job Title is less than 50 characters")]
public string JobTitle { get; set; }
public int Priority { get; set; }
// Relationships
[ForeignKey("Category")]
public int CategoryId { get; set; }
[ForeignKey("JobType")]
public int JobTypeId { get; set; }
[ForeignKey("UserRequestedBy")]
public int RequestedBy { get; set; }
[ForeignKey("UserCreatedBy")]
public int CreatedBy { get; set; }
// Navigation Properties
public virtual JobType JobType { get; set; }
public virtual Category Category { get; set; }
public virtual User UserRequestedBy { get; set; }
public virtual User UserCreatedBy { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
public virtual ICollection<JobNote> Notes { get; set; }
}
But when I try to run my application I get the following error:
Introducing FOREIGN KEY constraint 'FK_dbo.Jobs_dbo.Users_CreatedBy' on table 'Jobs' 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.
With cascade delete on by default, deleting a User has two cascade paths - RequestedBy and CreatedBy
Disabling the cascade deletion is exhibited in this question.