【问题标题】:Entity framework replaces delete+insert with an update. How to turn it off实体框架将删除+插入替换为更新。如何关闭它
【发布时间】:2015-08-13 07:34:20
【问题描述】:

我想删除数据库中的一行,然后用相同的 Id 再次插入,这听起来很荒谬,但这是场景:

领域类如下:

public class SomeClass
{
    public int SomeClassId { get; set; }
    public string Name { get; set; }
    public virtual Behavior Behavior { get; set; }
}

public abstract class Behavior
{
    public int BehaviorId { get; set; }
}

public class BehaviorA : Behavior
{
    public string BehaviorASpecific { get; set; }
}

public class BehaviorB : Behavior
{
    public string BehaviorBSpecific { get; set; }
}

实体上下文是

public class TestContext : DbContext
{
    public DbSet<SomeClass> SomeClasses { get; set; }
    public DbSet<Behavior> Behaviors { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

        modelBuilder.Entity<SomeClass>()
            .HasOptional(s => s.Behavior)
            .WithRequired()
            .WillCascadeOnDelete(true);

    }
}

现在可以执行这段代码来说明这一点 (在下面的代码中用 cmets 描述)

    using(TestContext db = new TestContext())
    {
        var someClass = new SomeClass() { Name = "A" };
        someClass.Behavior = new BehaviorA() { BehaviorASpecific = "Behavior A" };
        db.SomeClasses.Add(someClass);

        // Here I have two classes with the state of added which make sense
        var modifiedEntities = db.ChangeTracker.Entries()
                                 .Where(entity => entity.State != System.Data.Entity.EntityState.Unchanged).ToList();
        // They save with no problem
        db.SaveChanges();

        // Now I want to change the behavior and it causes entity to try to remove the behavior and add it again
        someClass.Behavior = new BehaviorB() { BehaviorBSpecific = "Behavior B" };

        // Here it can be seen that we have a behavior A with the state of deleted and 
        // behavior B with the state of added
        modifiedEntities = db.ChangeTracker.Entries()
                 .Where(entity => entity.State != System.Data.Entity.EntityState.Unchanged).ToList();

        // But in reality when entity sends the query to the database it replaces the 
        // remove and insert with an update query (this can be seen in the SQL Profiler) 
        // which causes the discrimenator to remain the same where it should change.
        db.SaveChanges();
    } 

如何更改此实体行为,以便删除和插入而不是更新?

【问题讨论】:

    标签: entity-framework inheritance ef-code-first code-first tph


    【解决方案1】:

    一个可能的解决方案是在 2 个不同的步骤中进行更改:在 someClass.Behavior = new BehaviorB() { BehaviorBSpecific = "Behavior B" }; 插入之前

    someClass.Behaviour = null;
    db.SaveChanges();
    

    该行为与数据库模型有关。 EF 中的 BehaviourA 和 B 与同一个 EntityRecordInfo 相关,具有相同的 EntitySet(行为)。 如果您在上下文中创建 2 个不同的 DbSet,您也会有相同的行为,因为 DB 模型保持不变。

    编辑
    另一种实现类似 1-1 关系结果的方法是使用 ComplexType。它们也适用于继承。 这里是一个例子

    public class TestContext : DbContext
    {
        public TestContext(DbConnection connection) : base(connection, true) { }
    
        public DbSet<Friend> Friends { get; set; }
        public DbSet<LessThanFriend> LessThanFriends { get; set; }
    }
    
    public class Friend
    {
        public Friend()
        {Address = new FullAddress();}
    
        public int Id { get; set; }
        public string Name { get; set; }
    
        public FullAddress Address { get; set; }
    }
    
    public class LessThanFriend
    {
        public LessThanFriend()
        {Address = new CityAddress();}
    
        public int Id { get; set; }
        public string Name { get; set; }
    
        public CityAddress Address { get; set; }
    }
    
    
    [ComplexType]
    public class CityAddress
    {
        public string Cap { get; set; }
        public string City { get; set; }
    }
    
    [ComplexType]
    public class FullAddress : CityAddress
    {
        public string Street { get; set; }
    }
    

    【讨论】:

    • 嗨,布比,感谢您的回答。但是我只是举了这个例子来说明我的观点,实际上并不是那么简单,我有一个工作单元正在跟踪更改,并且在用户真正想要这样做之前我无法保存它们。
    • 关于这个模型还有另一个问题。您不能将 1 行为附加到 2 SomeClass。您可以评估以将 Behavior 用作 ComplexType。
    • 我记得有一次我尝试了ComplexType,但是我不能使用继承(我的ComplexType实际上是一个抽象类),你知道一种将ComplexType与继承结合使用的方法吗?
    • 你可以使用它们...我用一个例子更新答案
    • 我必须首先感谢您的努力。但问题是,在两个不同的类中,您使用两种不同的数据类型(Friend 中的 FullAddress 和 LessThanFriend 中的 CityAddress)。我有一个具有地址类型属性的人(它是抽象的,可以是 cityAddress 或 fullAddress)。这个人是我的 LessThanFriend,我已经保存了它的 cityAddress,但过了一段时间她成了我的朋友,我想将她的地址更新为 fullAddress。这让我回到了我与她的最初问题! :)
    猜你喜欢
    • 1970-01-01
    • 2014-12-09
    • 2018-01-19
    • 2016-11-17
    • 2017-02-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多