Вопрос или проблема
Я использую 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;
}
У меня возникли ошибки сборки после генерации миграции:
Я попытался вручную указать, что это свойство сложное, используя метод 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 для получения актуальной информации и новых возможностей.