I have the following entity:
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public List<Employee> Employees { get; set; }
public int? HeadDepartmentId { get; set; }
public Department HeadDepartment { get; set; }
public List<Department> ChildDepartments { get; set; }
}
I Add-Migration and then try to update database and as a result:
Introducing FOREIGN KEY constraint 'FK_Departments_Departments_HeadDepartmentId' on table 'Departments' 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 try next:
builder.Entity<Department>()
.HasOne(p => p.HeadDepartment)
.WithMany(p => p.ChildDepartments)
.HasForeignKey(p => p.HeadDepartmentId).OnDelete(DeleteBehavior.ClientSetNull);
But it doesnt help.
Related
I am using EF Core. I want my base class to keep reference of CreateByUser, and LastModifiedByUser. Unfortunately I can only get it to work with one foreign key. When I try to add a second foreign key I get this error:
Introducing FOREIGN KEY constraint 'FK_Assignments_Users_LastModifiedByUserId' on table 'Assignments' 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. Note that I can use "Add-Migration" with out any errors, but once I run "Update-Database" it errors.
Below is the relevant code to the problem and error.
public abstract class DivBase
{
[Key]
public int Id { get; set; }
[Required]
public DateTimeOffset DateCreated { get; set; }
public int CreatedByUserId { get; set; }
[Required]
public DateTimeOffset LastDateModified { get; set; }
public int LastModifiedByUserId { get; set; }
[ForeignKey("CreatedByUserId")]
public DivUser CreatedByUser { get; set; }
[ForeignKey("LastModifiedByUserId")]
public DivUser LastModifiedByUser { get; set; }
}
public class DivUser
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(256)]
public string Name { get; set; }
[Required]
[MaxLength(256)]
public string Email { get; set; }
}
public class DivAssignment : DivBase, IDivEvent
{
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
}
public interface IDivEvent
{
[Required]
public DateTimeOffset StartDate { get; set; }
[Required]
public DateTimeOffset EndDate { get; set; }
}
Also, If I make one of the properties nullable it will compile, but I fear that will cause problems later.
Apparently you have a 2 Fks to the same table in the same row so imagine if you delete a user who has created an assignment and Modified one what should happen, delete the assignment what if other users modified it this will be nulls in heir tables.
so
You need to specify the CascadeOnDelete to false using FluentApi
In the ApplicationContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<DivAssignment>()
.HasRequired(c => c.CreatedByUser)
.WithMany(u => u.CreatedDivAssignments)
.HasForeignKey(c => c.CreatedByUserId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<DivAssignment>()
.HasRequired(c => c.LastModifiedByUser)
.WithMany(u => u.ModifiedDivAssignments)
.HasForeignKey(c => c.LastModifiedByUserId)
.WillCascadeOnDelete(false);
}
Then add-migration then update-database
I have 2 models:
public class Text
{
public long Id { get; set; }
public string Text { get; set; }
}
public class User
{
public int Id { get; set; }
public ICollection<Text> Texts { get; set; }
}
My model build on user is that
e.HasMany(o => o.Texts).WithOne().HasForeignKey(d => d.Id).IsRequired();
When I try to run:
dotnet ef migrations add
I get this error:
with foreign key properties {'Id' : long} cannot target the primary
key {'Id' : int} because it is not compatible. Configure a principal
key or a set of compatible foreign key properties for this
relationship.
UPDATE:
It should be able for new models to have a collection of the table Texts like:
public class Customer
{
public int Id { get; set; }
public ICollection<Text> Texts { get; set; }
}
....
e.HasMany(o => o.Texts).WithOne().HasForeignKey(d => d.Id).IsRequired();
Had similar problem using EF Core but didn't want to include the (equivalent in my class) UserId on the dependent entity Text, just to make happy EF. Finally found that you can replace the primary key used in the relationship (UserId)
using HasPrincipalKey()
modelBuilder.Entity<User>()
.HasMany(t => t.Texts)
.WithOne()
.HasPrincipalKey(u => u.Text);
Firstly, change your Model naming please,
public class Text
{
public long Id { get; set; }
public int UserId { get; set; }// add a foreign key that could point to User.Id
public string Body { get; set; }//you cannot have a string property called "Text".
public virtual User Owner { get; set; }
}
public class User
{
public int Id { get; set; }
public virtual ICollection<Text> Texts { get; set; } = new HashSet<Text>();
}
builder.Entity<Text>(table =>
{
table.HasKey(x => x.Id);
table.HasOne(x => x.User)
.WithMany(x => x.Texts)
.HasForeignKey(x => x.UserId)
.HasPrincipalKey(x => x.Id)//<<== here is core code to let foreign key userId point to User.Id.
.OnDelete(DeleteBehavior.Cascade);
});
the reason we have to figure out which key is referred is because of multiple primary keys. I saw it once in MSDN, but cannot find it back.
You can use shadow properties for foreign keys, it looks popular now.
public class Text
{
public long Id { get; set; }
public string Body { get; set; }
public virtual User Owner { get; set; }
}
public class User
{
public int Id { get; set; }
public virtual ICollection<Text> Texts { get; set; } = new HashSet<Text>();
}
builder.Entity<Text>(table =>
{
table.HasKey(x => x.Id);
// Add the shadow property to the model
table.Property<int>("UserId");
table.HasOne(x => x.User)
.WithMany(x => x.Texts)
.HasForeignKey("UserId")//<<== Use shadow property
.HasPrincipalKey(x => x.Id)//<<==point to User.Id.
.OnDelete(DeleteBehavior.Cascade);
});
In the EF context configuration, specifically in the HasForeignKey() you are supposed to specify Which property on the Text model should be the foreign key that points to the User model?
Since User model's primary key is an int, the foreign key pointing from Text to User should naturally also be an int.
I think the mistake you've made is that you are configuring the PK of Textto also be the FK for the relationship Text -> User. Try to change your Text model to :
public class Text
{
public long Id { get; set; }
public string Text{ get; set; }
public int UserId { get; set; }
}
And your configuration to:
e.HasMany(o => o.Texts).WithOne().HasForeignKey(d => d.UserId).IsRequired();
You can simply drop all the migrations or the migration that made that Id, drop the database (if it is small or has no data) and add a clean migration
I was facing the same issue in one-to-one relationship. If you are facing the issue in one-one relationship. Then try this:
public partial class document
{
public document()
{
groups = new group();
}
public int? group_id { get; set; }
public virtual group groups { get; set; }
}
[Table("group")]
public class group
{
[Key]
[Column("group_id")]
public int group_id { get; set; }
[ForeignKey(nameof(group_id))]
public virtual document document { get; set; }
}
Each document has single group. So, we can consider these settings.
modelBuilder.Entity<group>().HasOne(a => a.document)
.WithOne(y => y.groups).HasForeignKey<document>(b => b.group_id);
I have a schema Definitions which I would like to be able to reference itself. As I need meta data about the reference, there's a coupling schema named Associations. I'm using Entity Framework's fluent API in conjunction with data annotation attributes.
Definitions:
public class Definition
{
[Key]
public int Id { get; set; }
// ...
public virtual ICollection<Association> Associations { get; set; }
}
Associations:
public class Association
{
[Key]
public int Id { get; set; }
public int TypeId { get; set; }
public int AssociatedDefinitionId { get; set; }
public int RootDefinitionId { get; set; }
public virtual AssociationType Type { get; set; }
public virtual Definition AssociatedDefinition { get; set; }
public virtual Definition RootDefinition { get; set; }
}
OnModelCreating:
modelBuilder.Entity<Association>()
.HasRequired(p => p.AssociatedDefinition)
.WithRequiredPrincipal();
modelBuilder.Entity<Association>()
.HasRequired(p => p.RootDefinition)
.WithRequiredPrincipal();
I use MySQL as the database engine.
When I try to save a definition entity with an empty association collection, I get a constraint violation:
Cannot add or update a child row: a foreign key constraint fails
("u0228621_8"."Definitions", CONSTRAINT
"FK_Definitions_Associations_Id" FOREIGN KEY ("Id") REFERENCES
"Associations" ("Id"))
What am I doing wrong?
You have defined your association class with all relationships being "required:required" because of the WithRequiredPrincipal which doesn't seem to be what you want. Since the Associations collection appears (from the comments) to be the relation from the Root definitions, the mapping should come from definition, like so:
// Foreign key mappings included.
modelBuilder.Entity<Definition>().HasMany(d => d.Assocations)
.WithRequired(a => a.RootDefinition).HasForeignKey(a => a.RootDefinitionId);
modelBuilder.Entity<Association>().HasRequired(a => a.AssociatedDefinition)
.HasForeignKey(a => a.AssociatedDefinitionId);
So the Associations collection may be empty, but every Association requires a RootDefinition and AssociatedDefinition.
I am developing a sample application where people can place bets on sports events and earn points. It has the following Entity Framework Code-First models:
public class Person
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Race
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class RaceBet
{
[Key]
public int Id { get; set; }
[Required]
public int RaceId { get; set; }
[Required]
public int PersonId { get; set; }
[Required]
public int CompetitorId { get; set; }
public virtual Race Race { get; set; }
public virtual Person Person { get; set; }
public virtual Person Competitor { get; set; }
}
A Person can place a bet for a Race and he can bet on any other Person (Competitor).
The models will produce the following error:
Introducing FOREIGN KEY constraint 'FK_dbo.RaceBets_dbo.People_PersonId' on table 'RaceBets' 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.
I tried removing the OneToManyCascadeDeleteConvention, adding fluent configurations to prevent cascade delete for RaceBet and all other variations of the api, but everything fails.
modelBuilder
.Entity<RaceBet>()
.HasRequired(x => x.Person)
.WithMany()
.HasForeignKey(x => x.PersonId)
.WillCascadeOnDelete(false);
How can I resolve this? Is the concept behind my models wrong?
Thanks!
Thanks to Oleg for his comment:
I can't to reproduce exception with this code: protected override void
OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Add(new
System.Data.Entity.ModelConfiguration.Conventions.OneToManyCascadeDeleteConvention());
modelBuilder .Entity() .HasRequired(x => x.Person)
.WithMany() .HasForeignKey(x => x.PersonId)
.WillCascadeOnDelete(false); }
This fixed the model creation.
I have an entity that excludes entities of the same type under certain conditions. In order to achieve this, I have an entity class like:
public class Entity
{
public int ID { get; set; }
public virtual ICollection<EntityExcludedEntity> ExcludedEntities { get; set; }
}
public class ExcludedEntity
{
public int ID { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
public int EntityID { get; set; }
public virtual Entity Entity { get; set; }
public int ExcludedEntityID { get; set; }
public virtual Entity ExcludedEntity { get; set; }
}
//declared in the ExcludedEntity mapping class.
public ExcludedEntityMapping()
{
HasRequired(t => t.Entity).WithMany(t => t.ExcludedEntity).HasForeignKey(t => t.EntityID)
HasRequired(t => t.ExcludedEntity).WithMany(t => t.ExcludedEntity).HasForeignKey(t => t.ExcludedEntityID);
}
This causes in EF creating a third column and foreign key field called Entity_ID in my model. Seems like it thinks I have another relationship defined here but I don't understand why.
Here is the part related to foreign keys in the tables created:
.ForeignKey("dbo.Entities", t => t.EntityID)
.ForeignKey("dbo.Entities", t => t.ExcludedEntityID)
.ForeignKey("dbo.Entities", t => t.Entity_ID)
This post helped me find the answer.
Basically, EF cannot have two foreign keys to the same entity field. If you need to create two foreign key to the same entity you should bind them to different fields. So in this example:
public class Entity
{
public int ID { get; set; }
public virtual ICollection<EntityExcludedEntity> ExcludingEntities { get; set; }
public virtual ICollection<EntityExcludedEntity> ExcludedFromEntities { get; set; }
}
and this configuration:
public DBConceptAnswerExcludedAnswerMapping()
{
HasRequired(t => t.Entity).WithMany(t => t.ExcludingEntities).HasForeignKey(t => t.EntityID);
HasRequired(t => t.ExcludedEntity).WithMany(t => t.ExcludedFromEntities).HasForeignKey(t => t.ExcludedEntityID);
}
would solve the problem.