Я пытаюсь добиться чего-то в EF Core, что очень хорошо сработало для меня в EF 6.
Я сериализую содержимое свойства List<T>
в виде строки Json в БД. <T>
может быть чем угодно, поскольку Json.Net заботится о сериализации всего, что мы ему подбрасываем. Моя коллекция предоставляет строковое свойство Json
и сама заботится о сериализации/десериализации.
Этот подход удобен и эффективен для структурированных вложенных данных, где реляционная модель привела бы к ненужным накладным расходам и сложности.
В EF 6 я бы сделал что-то вроде этого:
[ComplexType]
public class SelfSerializingCollection<T> : Collection<T>
{
public void AddRange(IEnumerable<T> collection)
{
foreach (var item in collection)
{
Add(item);
}
}
protected string Json
{
get { return JsonConvert.SerializeObject(this); }
private set
{
Clear();
if (value == null)
{
return;
}
AddRange(JsonConvert.DeserializeObject<T[]>(value));
}
}
}
EF 6 не поддерживает сопоставление универсальных типов, поэтому мы предоставим конкретную реализацию для каждого типа списка, который нам может понадобиться:
public class PhoneNumberCollection : SelfSerializingCollection<PhoneNumber> { }
А затем используйте его следующим образом:
public class Contact {
public PhoneNumberCollection PhoneNumbers { get; set; }
}
И это было все. Теперь я пытаюсь добиться того же в EF Core 2.0.
Вот что у меня есть до сих пор. Класс SelfSerializingCollection<T>
не изменился.
public class Contact {
// EF Core supports generic types so we don't need a concrete implementation
// for each collection type.
public SelfSerializingCollection<PhoneNumber> PhoneNumbers { get; set; }
}
public class MyDbContext : DbContext
{
// ...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// EF Core does not support the [ComplexType] attribute
// but we now have .OwnsOne() in EF Core 2
modelBuilder.Entity<Contact>().OwnsOne(p => p.PhoneNumbers);
}
}
Все идет нормально. EF Core сопоставляет столбец PhoneNumbers_Json
в базе данных. Чтение и создание новых записей работает просто отлично.
Но, в отличие от EF 6, любые изменения в коллекции PhoneNumbers
существующего объекта не сохраняются обратно в базу данных. Я обновляю типичным методом PUT с помощью _context.Entry(contactModelFromRequestBody).State = EntityState.Modified;
- так же, как и раньше. Но по какой-то причине EF Core не сохраняет мое строковое свойство Json
обратно в БД для объекта Modified
.
Любые идеи?