Entity Framework 发现可能存在竞争级联删除。但是,在使用中这是不可能的。我需要知道如何告诉实体框架这个。
此应用程序用于处理政治志愿者,这些志愿者可以在州级、县级和/或竞选级别提供帮助。
我看到两个问题(也许还有更多)。
我如何告诉 Entity Framework 和 SQL Server 在操作中不会有两个所有者都试图级联删除同一个事件?
相关问题。在 EventConfiguration.Configure 中,我如何告诉 DB 对于三个外键强制执行,在任何给定记录中,其中两个外键必须为空?
我运行 Update-Database 的错误是:
Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_Events_Counties_CountyId' on table 'Events' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
解决方案在此处作为 zip 提供。 或者您可以查看以下课程:
public class Campaign
{
public int Id { get; private set; }
public string Name { get; private set; }
public required State State { get; set; }
public ICollection<Event> Events { get; set; }
public ICollection<User> Followers { get; set; }
protected Campaign(int id, string name, DateTime created)
{
Id = id;
Events = default!;
Followers = default!;
}
public Campaign()
{
Events = new List<Event>();
Followers = new List<User>();
}
}
public class CampaignConfiguration : IEntityTypeConfiguration<Campaign>
{
public void Configure(EntityTypeBuilder<Campaign> builder)
{
builder.HasIndex(new[] { "Name", "StateId" }).IsUnique();
builder.HasIndex("StateId");
builder.HasMany(x => x.Events)
.WithOne(x => x.Campaign).OnDelete(DeleteBehavior.Cascade);
}
}
public class County
{
public int Id { get; private set; }
public string Name { get; private set; }
public required State State { get; set; }
public ICollection<Event> Events { get; set; }
public ICollection<User> Followers { get; set; }
protected County(int id, string name)
{
Id = id;
Events = default!;
Followers = default!;
}
public County()
{
Events = new List<Event>();
Followers = new List<User>();
}
}
public class CountyConfiguration : IEntityTypeConfiguration<County>
{
public void Configure(EntityTypeBuilder<County> builder)
{
builder.HasIndex(new[]{"Name", "StateId"}).IsUnique();
builder.HasMany(x => x.Events)
.WithOne(x => x.County).OnDelete(DeleteBehavior.Cascade);
}
}
public class Event
{
public int Id { get; private set; }
public required User Owner { get; set; }
public Campaign? Campaign { get; set; }
public County? County { get; set; }
public State? State { get; set; }
protected Event(int id, DateTime created)
{
Id = id;
}
public Event()
{
}
}
public class EventConfiguration : IEntityTypeConfiguration<Event>
{
public void Configure(EntityTypeBuilder<Event> builder)
{
// fails!
// builder.HasIndex(e => new[] { "CampaignId", "CountyId", "StateId" }).IsUnique();
}
}
public class State
{
public int Id { get; private set; }
public string Name { get; private set; }
public ICollection<County> Counties { get; set; }
public ICollection<Campaign> Campaigns { get; set; }
public ICollection<Event> Events { get; set; }
public ICollection<User> Followers { get; set; }
protected State(int id, string name)
{
Id = id;
Counties = default!;
Campaigns = default!;
Events = default!;
Followers = default!;
}
public State()
{
Counties = new List<County>();
Campaigns = new List<Campaign>();
Events = new List<Event>();
Followers = new List<User>();
}
}
public class StateConfiguration : IEntityTypeConfiguration<State>
{
public void Configure(EntityTypeBuilder<State> builder)
{
builder.HasMany(x => x.Counties)
.WithOne(x => x.State).OnDelete(DeleteBehavior.Cascade);
builder.HasMany(x => x.Campaigns)
.WithOne(x => x.State).OnDelete(DeleteBehavior.Cascade);
builder.HasMany(x => x.Events)
.WithOne(x => x.State).OnDelete(DeleteBehavior.Cascade);
}
}
public class User
{
public int Id { get; private set; }
public ICollection<Campaign> Campaigns { get; set; }
public ICollection<County> Counties { get; set; }
public ICollection<State> States { get; set; }
public ICollection<Event> Events { get; set; }
protected User(int id, string name, string email)
{
Id = id;
Campaigns = default!;
Counties = default!;
States = default!;
Events = default!;
}
public User()
{
Campaigns = new List<Campaign>();
Counties = new List<County>();
States = new List<State>();
Events = new List<Event>();
}
}
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
}
}