实体框架用更新替换delete + insert。如何关闭它

时间:2015-08-13 07:34:20

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

我想删除数据库中的一行并使用相同的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);

    }
}

现在可以执行此代码来演示这一点 (在下面的代码中用注释描述)

    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();
    } 

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

1 个答案:

答案 0 :(得分:0)

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

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

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

修改
实现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; }
}