我最近在EF核心3.1.1中遇到了一个奇怪的问题。我们正在尝试从EF6迁移到EF核心,拥有实体的行为与EF6中的复杂类型不同。当拥有的实体由空对象初始化时,EF无法检测到更改。仅针对MSSQL,针对“内存中”数据库,就会出现此问题,一切似乎都很好。
public class OwnedEntityProxyTests
{
[Fact]
public void InMemoryTest()
{
Assert.True(Test(new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "Test")));
}
[Fact]
public void MsSqlTest()
{
Assert.True(Test(new DbContextOptionsBuilder<TestContext>()
.UseSqlServer("Data Source=.;MultipleActiveResultSets=True;Integrated Security=True")));
}
private static bool Test(DbContextOptionsBuilder<TestContext> builder)
{
var options = builder.UseLazyLoadingProxies().Options;
using (var ctx = new TestContext(options))
{
ctx.TestEntities.RemoveRange(ctx.TestEntities.ToArray());
ctx.TestEntities.Add(new TestEntity());
ctx.SaveChanges();
}
using (var ctx = new TestContext(options))
{
var e = ctx.TestEntities.Single();
e.TestOwnedEntity.Code = "test";
return ctx.ChangeTracker.Entries().Any(o => o.State != EntityState.Unchanged);
}
}
}
public class TestContext : DbContext
{
public TestContext() : base(new DbContextOptionsBuilder<TestContext>()
.UseSqlServer("Data Source=.;MultipleActiveResultSets=True;Integrated Security=True")
.UseLazyLoadingProxies()
.Options)
{
}
public TestContext(DbContextOptions options) : base(options)
{
}
public DbSet<TestEntity> TestEntities { get; set; }
}
public class TestEntity
{
public long Id { get; set; }
public virtual TestOwnedEntity TestOwnedEntity { get; private set; } = new TestOwnedEntity();
}
[Owned]
public class TestOwnedEntity
{
public string Code { get; set; }
}
在此示例中,上下文应检测到更改。 “在内存数据库中”可以正确检测到它,但是MS Sql提供程序无法检测到它。这很可能是由于缺少拥有类型周围的代理引起的。当拥有类型的所有属性均为默认属性且未初始化时,所拥有实体为null时,缺少代理。
您能给我一些提示以正确设置它吗?我不想删除拥有实体的默认初始化,这将迫使我们检查所有地方是否拥有实体为null。
我相信您必须为Equals
实现方法TestOwnedEntity
,类似:
public override bool Equals(object obj)
{
var other = obj as TestOwnedEntity;
if (other == null) return false;
if (object.ReferenceEquals(this, obj) return true;
return other.Code == this.Code;
}