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. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
