Поддерживает ли EF Core ComplexType в свойстве Owned?

Вопрос или проблема

Я использую ComplexTypeAttribute для некоторых столбцов данных, которые я хочу сгруппировать вместе, как:

[ComplexType]
public record TrashData(DateTime? Value)
{
    public Identity By { get; init; } = Identity.Unknown;

    private string _reason = string.Empty;
    public string? Reason
    {
        get => _reason;
        init => _reason = string.IsNullOrWhiteSpace(value) ? string.Empty : value;
    }

    private static readonly TrashData _available = new TrashData((DateTime?)null);
    public static TrashData Available => _available;
}
[ComplexType]
public record Identity(string IdKind = "GUID", string? Value = null)
{
  public static readonly Identity Unknown = new("_","_");
}

Я не обнаружил проблем с добавлением ComplexType внутри другого.

Но когда я добавил ComplexType внутри свойства Owned, как в следующем примере:

//(Я использую Asp Identity)
public class User : IdentityUser
{
    public required UserMetaData MetaData { get; set; } = new(default);
}
[Owned]
public record UserMetaData(string Id)
{
    public TrashData Trashed_ { get; set; } = TrashData.Available;
}

У меня возникли ошибки сборки после генерации миграции:

'OwnedNavigationBuilder' не содержит определения для 'ComplexProperty'

Я попытался вручную указать, что это свойство сложное, используя метод Fluent, как это, но, похоже, его там нет:

builder.Entity<User>(e =>
{
//  e.ComplexProperty(x => x.MetaData.Trashed_); // Можно вызвать ComplexProperty

    e.OwnsOne(
        x => x.MetaData,
        o =>
        {
            o.WithOwner().HasPrincipalKey(x => x.Id).HasForeignKey(x => x.Id);
            // o.ComplexProperty(x => x.Trashed_); // Нельзя вызвать сложное свойство здесь.
        }
    );
}

Так поддерживает ли EF Core 8 сложный тип внутри собственного свойства или нет?

Примечание: Миграция генерируется против SQLite.

Ответ или решение

Вопрос: Поддерживает ли Entity Framework Core (EF Core) использование ComplexType в составе Owned свойств?

Разберем ваш вопрос по шагам, учитывая представленный код и описание проблемы.

1. Понимание концепции сложности

Сначала стоит отметить, что в EF Core термин ComplexType обозначает класс, который можно использовать для группировки связанных свойств, но который не имеет собственного жизненного цикла в базе данных. Ваша реализация TrashData и Identity как "сложных типов" с использованием атрибута [ComplexType] действительно является правильным подходом.

2. Использование Owned типов

Owned типы в EF Core служат для обозначения объектов, которые не существуют самостоятельно, а являются частью другого объекта. В вашем случае UserMetaData ссылается на TrashData как на собственность, что является корректным применением концепции Owned типов.

3. Проблема с миграциями

С учетом вашего кода и ошибки, которую вы получили:

'OwnedNavigationBuilder' does not contain a definition for 'ComplexProperty'

Эта проблема возникает из-за того, что функциональность ComplexProperty не поддерживается внутри Owned свойств в EF Core. Существует особая логика работы с Owned типами, и они обрабатываются иначе, чем стандартные сложные типы.

4. Решение проблемы

В EF Core на данный момент (версия 8) действительно не поддерживается возможность использования ComplexType в рамках Owned типов напрямую через конфигурацию. Однако вы можете работать с TrashData как с простым свойством внутри класса UserMetaData, что позволит избежать проблемы с миграциями.

Вот пример, как вы можете изменить определение класса UserMetaData:

[Owned]
public record UserMetaData(string Id)
{
    public DateTime? TrashedValue { get; set; }
    public string? TrashedReason { get; set; }

    public TrashData Trashed_
    {
        get => new TrashData(TrashedValue) { Reason = TrashedReason };
        set
        {
            TrashedValue = value.Value;
            TrashedReason = value.Reason;
        }
    }
}

5. Заключение

Итак, на текущий момент EF Core 8 не поддерживает использование ComplexType внутри Owned свойств. Вы можете использовать стандартные свойства для хранения значений и реализовать логику преобразования для работы с вашими сложными типами. Это позволит успешно создавать миграции и поддерживать целостность базы данных.

Если в будущем EF Core обновит свою поддержку для данного сценария, новые возможности можно будет легко внедрить в ваш текущий код. Рекомендуется следить за обновлениями в документации EF Core для получения актуальной информации и новых возможностей.

Оцените материал
Добавить комментарий

Капча загружается...