#c# #entity-framework #ef-core-2.2
#c# #сущность-фреймворк #ef-ядро-2.2
Вопрос:
Я хотел бы отобразить в ядре Ef сложный тип (другими словами, тип, не сопоставленный напрямую с таблицей), который содержит список объектов, которые напрямую сопоставляются с таблицей.
Рассмотрим следующий пример ниже, где вы обнаружите, что логика дневника (из которых я сейчас показываю только addEntry) отделена от класса запроса, поскольку она не имеет никакого отношения к присутствию.
У меня нет проблем с использованием.OwnsOne в ядре Ef при использовании более простых типов, где данные хранятся в одной таблице (например: здесь это будет в таблице запросов); но я понятия не имею или понятия, как бы я сопоставил при настройке этой ситуации.
- Модель C #:
public class Request : DbEntity {
public Diary { get; set; }
}
public class DiaryEntry : DbEntity {
public DateTimeOffset Timestamp { get; set; }
public Request Request { get; set; }
public string Message { get; set; }
}
public class Diary {
private readonly List<DiaryEntry> _entries = new List<DiaryEntry>();
public Request Request { get; set; }
public IEnumerable<DiaryEntry> Entries => _entries;
public Diary AddEntry(DiaryEntry diaryEntry) {
if(diaryEntry != null)
_entries.Add(diaryEntry);
return this;
}
}
- Структура SQL
- Запросы — это таблица, которая сопоставляется в EFCore с запросом объекта
- DiaryEntries — это таблица, которая существует в EFCore и косвенно сопоставляется с DbSet с запросом как «hasOne», чтобы он имел отношение.
- Таблица «Дневник» не существует, это «сложный тип», который инкапсулирует логику, поэтому мне не нужно иметь дело с ней в типе «Запрос» в C#
Комментарии:
1. Поскольку DiaryEntry ссылается на запрос, почему бы не добавить свойство навигации по коллекции в класс запроса, которое позволило бы вам использовать синтаксис EF Core fluent для извлечения списка? Например.
public ICollection<DiaryEntry> DiaryEntries { get; set; }
2. Это именно то, чего я хочу избежать, поскольку «Дневник» будет содержать логику, которая полезна только для сбора DiaryEntries и не полезна для класса Request. Другими словами, я хочу максимально уважать SRP и не загромождать запрос логикой, которая не имеет реального значения для самого «запроса».
Ответ №1:
Я не верю, что что-либо подобное поддерживается в Entity Framework, поскольку сложные типы предназначены для поддержки организации свойств одной таблицы в связанные классы без реляционных таблиц. В вашем случае вы хотели бы использовать реляционные таблицы и сопоставить промежуточный класс, чтобы избежать наличия правил управления дочерней коллекцией в родительском классе.
Один из вариантов, который я могу предложить, чтобы помочь решить проблему разделения проблем, которые вы, по-видимому, хотите иметь между вашими классами, — это использовать методы расширения для специфичной для коллекции логики, которую вы хотите предоставить для дневника.
Например:
[Table("Requests")]
public class Request
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int RequestId { get; set; }
public string Name { get; set; }
public virtual IEnumerable<DiaryEntry> Diary { get; protected set; } = new List<DiaryEntry>();
}
[Table("DiaryEntries")]
public class DiaryEntry
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DiaryEntryId { get; set; }
public string Value { get; set; }
public virtual Request Request { get; set; }
}
Здесь мы раскрываем Дневник, IEnumerable<DiaryEntry>
чтобы потребители объекта не могли изменять коллекцию и т. Д. Оттуда функциональность дневника может управляться расширениями:
public static class DiaryExtensions
{
public static DiaryEntry AddEntry(this IEnumerable<DiaryEntry> diary, DiaryEntry newEntry)
{
ICollection<DiaryEntry> diaryList = (ICollection<DiaryEntry>)diary;
if (newEntry != null)
diaryList.Add(newEntry);
return newEntry;
}
}
Лично, хотя у меня была бы эта логика в запросе, поскольку записи дневника связаны с запросом. Чтобы отделить логику, специфичную для дневника, я бы использовал частичные классы, но сохранял ответственность за поддерживаемое поведение в классе, который их содержит.
Комментарии:
1. На самом деле я действительно пошел по аналогичному маршруту сейчас, настолько прагматично, насколько это возможно, и действительно использую функциональность частичных классов, которую мы имеем в языке, чтобы сделать ее по крайней мере «визуально» отдельной. Однако я подумал, что в EF могло быть другое решение, но если нет, то это вполне приемлемо. Спасибо за ваш ответ!