Description
I recently struggle with strange problem in EF core 3.1.1. We are trying to migrate from EF6 to EF core and Owned entities behave differently then Complex types in EF6. When owned entity is initialized by empty object then EF fails to detect change. This problem is occuring just against MSSQL, against "In memory" database everything seems to be fine.
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; }
}
In this example context should detect change. "In memory database" detects it correctly, but MS Sql provider fails to detect it. It is most likely caused by missing Proxy around owned type. Proxy is missing when all properties of owned type are default and without initialization the owned entity is null.
Could you please give me some tip how to setup it correctly? I don't want to remove default initialization of owned entities, it would force us to check everywhere if Owned entity is null or not.
Whole project is on github
Further technical details
EF Core version: 3.1.2
Database provider: SqlServer
Target framework: core 3.1
Operating system: Windows