EF core 3.1.1 - проблема прокси-сервера, принадлежащего объекту

Недавно я столкнулся со странной проблемой в EF core 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.

Не могли бы вы дать мне совет, как его правильно настроить? Я не хочу удалять инициализацию по умолчанию для принадлежащих сущностей, это заставило бы нас проверять везде, является ли Owned entity нулевым или нет.

весь проект находится на github


person Bohumír Pospíšil    schedule 05.03.2020    source источник
comment
Какие свойства используются по умолчанию при использовании new TestEntity()?   -  person Train    schedule 05.03.2020
comment
это можно увидеть, если прокрутить вниз. Просто TestOwnedEntity инициализирован новым экземпляром   -  person Bohumír Pospíšil    schedule 05.03.2020


Ответы (2)


Я считаю, что вы должны реализовать метод 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;
}
person Ricardo Peres    schedule 05.03.2020
comment
Я попробовал это несколько дней назад, и это не помогло. Я добавил его в это решение (на всякий случай, это не повредит), и он находится на github ссылка - person Bohumír Pospíšil; 06.03.2020

В конце они помогли на основном форуме EF https://github.com/dotnet/efcore/issues/20213

public class TestEntity
{
    public long Id { get; set; }

    private TestOwnedEntity _testOwnedEntity;
    public virtual TestOwnedEntity TestOwnedEntity
    {
        get
        {
            if (_testOwnedEntity == null)
            {
                _testOwnedEntity = new TestOwnedEntity();
            }
            return _testOwnedEntity;
        }
        private set { _testOwnedEntity = value; }
    }
}

изменения в моем тесте вы можете найти здесь: https://github.com/PospisilBohumir/EfCoreTests/tree/FinalFix

person Bohumír Pospíšil    schedule 09.03.2020