Entity Framework Code First и коллекции примитивных типов - PullRequest
10 голосов
/ 01 декабря 2011

При создании классов POCO, которые содержат коллекции примитивных типов и сохраняются в EF Code First, лучший совет, который я нашел до сих пор, - это создать новый класс, имеющий идентификатор плюс тип примитива:

Entity Framework и модели с простыми массивами

Если у меня есть несколько классов, которым требуются свойства типа ObservableCollection<string>, и замените их на ObservableCollection<EntityString> (где EntityString - это пользовательский тип сId и строковое свойство), в итоге я получаю таблицу EntityString, в которой есть несколько столбцов внешнего ключа, по одному для каждого свойства типа ObservableCollection<EntityString> для всех конкретных типов с такими свойствами.

Это приводит краздутость столбцов внешнего ключа, в большинстве своем равных нулю, в таблице EntityString.

Один из подходов заключается в создании подкласса EntityString и использовании модели Таблица на тип для этих подклассов.,Однако это требует внесения неуклюжих изменений в объектную модель просто для приспособления к Entity Framework.

Вопросы:

  • Является ли инкапсулирующий тип лучшим способом управления Collection<PrimitiveType>?
  • Если да, то каковы плюсы и минусы в разрешении нескольких (многих) столбцов внешнего ключа по сравнению с созданием пользовательских таблиц для типа (за счет неудобной модели)?

1 Ответ

5 голосов
/ 01 декабря 2011

Повышение простого типа до сущности является одним из вариантов.Если вы хотите использовать эту новую сущность примитивного типа в большем количестве отношений, лучше полностью удалить свойства навигации из этой сущности и использовать независимую ассоциацию (без свойств FK).

public class StringEntity
{
    public int Id { get; set; }
    public string Text { get; set; }
}

и отображение:

modelBuilder.Entity<Foo1>().HasMany(f => f.Strings).WithOptional();
modelBuilder.Entity<Foo2>().HasMany(f => f.Strings).WithOptional();

В базе данных вы получите новый обнуляемый FK для каждого связанного участника - избежать этого невозможно, кроме как создать специальный класс StringEntity для участника (не используйте для этого наследование, поскольку это влияет на производительность).

Существует альтернатива:

public class StringEntity
{
    public int Id { get; set; }
    public List<string> Strings { get; private set; }

    public string Text 
    {
        get
        {
            return String.Join(";", Strings);
        }

        set
        {
            Strings = value.Split(";").ToList();
        }
    }   
}

В этом случае вам не нужен связанный тип сущности (и дополнительная таблица), но ваша сущность загрязнена дополнительным свойством Text, которое предназначено только для персистентности.

...