entity-framework – 删除具有一对多关系的子项的父项
我有一个带有Entity Framework 5.0 e Sql Server CE 4.0的.NET4.0应用程序.
我有两个实体,一对多(父/子)关系.我已将其配置为在父删除时级联删除,但由于某种原因它似乎不起作用. 这是我的实体的简化版本: public class Account { public int AccountKey { get; set; } public string Name { get; set; } public ICollection<User> Users { get; set; } } internal class AccountMap : EntityTypeConfiguration<Account> { public AccountMap() { this.HasKey(e => e.AccountKey); this.Property(e => e.AccountKey).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(e => e.Name).IsRequired(); } } public class User { public int UserKey { get; set; } public string Name { get; set; } public Account Account { get; set; } public int AccountKey { get; set; } } internal class UserMap : EntityTypeConfiguration<User> { public UserMap() { this.HasKey(e => e.UserKey); this.Property(e => e.UserKey).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(e => e.Name).IsRequired(); this.HasRequired(e => e.Account) .WithMany(e => e.Users) .HasForeignKey(e => e.AccountKey); } } public class TestContext : DbContext { public TestContext() { this.Configuration.LazyLoadingEnabled = false; } public DbSet<User> Users { get; set; } public DbSet<Account> Accounts { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); modelBuilder.Conventions.Remove<StoreGeneratedIdentityKeyConvention>(); modelBuilder.LoadConfigurations(); } } 连接字符串: <connectionStrings> <add name="TestContext" connectionString="Data Source=|DataDirectory|TestDb.sdf;" providerName="System.Data.SqlServerCe.4.0" /> </connectionStrings> 以及我应用程序工作流程的简化版本: static void Main(string[] args) { try { Database.SetInitializer(new DropCreateDatabaseAlways<TestContext>()); using (var context = new TestContext()) context.Database.Initialize(false); Account account = null; using (var context = new TestContext()) { var account1 = new Account() { Name = "Account1^" }; var user1 = new User() { Name = "User1",Account = account1 }; context.Accounts.Add(account1); context.Users.Add(user1); context.SaveChanges(); account = account1; } using (var context = new TestContext()) { context.Entry(account).State = EntityState.Deleted; context.SaveChanges(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("nPress any key to exit..."); Console.ReadLine(); } 当我尝试删除父实体时,它会抛出:
我相信我的关系配置还可以(followed the documentation).我也搜索了guidelines on deleting detached entities. 我真的不明白为什么删除不起作用.我想避免加载所有子项,逐个删除它们并删除父项,因为必须有一个更好的解决方案. 解决方法将实体的状态设置为已删除并为此实体调用DbSet< T> .Remove是不一样的.不同之处在于,设置状态仅将根实体(传递给context.Entry的实体)的状态更改为已删除但不更改相关实体的状态,而如果使用级联删除配置关系,则删除会执行此操作. 如果你得到一个例外实际上取决于孩子(全部或只是一部分)被附加到上下文.这导致了一种有点难以遵循的行为: >如果您调用删除,则无论子项是否已加载,都不会出现异常.仍然存在差异: >如果子项附加到上下文,EF将为每个附加的子项生成DELETE语句,然后为父项生成(因为删除确实将它们全部标记为已删除) >如果将根实体的状态设置为“已删除”,则可能会出现异常: >如果孩子被附加到上下文,他们的状态将不会被设置为已删除,并且EF会抱怨您尝试删除所需关系中的主体(根实体)而不删除受抚养人(子女)或至少没有将其外键设置为另一个未处于“已删除”状态的根实体.这是您的例外:帐户是根,user1是帐户和调用context.Entry(帐户).State = EntityState.Deleted;还会将状态为“未更改”的user1附加到上下文中(或者在SaveChanges中更改检测将执行此操作,我不确定是否与此相关). user1是account.Users集合的一部分,因为关系fixup在第一个上下文中将它添加到集合中,尽管您没有在代码中明确添加它. 在我看来使用删除… using (var context = new TestContext()) { context.Accounts.Attach(account); context.Accounts.Remove(account); context.SaveChanges(); } …显然是首选方式,因为Remove的行为更像是您对级联删除所需的关系(在您的模型中就是这种情况).手动状态改变的行为对其他实体的状态的依赖性使得它更难以使用.我认为它仅作为特殊情况的高级用法. 这种差异并不广为人知或有记载.我看过很少有关于它的帖子.我现在唯一能找到的就是this one by Zeeshan Hirani. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |