EF Code First не генерирующая таблица для ICollection <string> - PullRequest
14 голосов
/ 20 ноября 2011

Мне бы хотелось, чтобы свойство ICollection ниже в одном из моих классов данных (назовем его «Foo»)

public class Foo
{
    [Key]
    public int FooId { get; set; }
    public string SomeValueOrOther { get; set; }
    public virtual ICollection<string> AllowedBars { get; set; }
}

Я могу добавить строковые значения при использовании контекста сущности, но они этого не делают"иди куда угодно".Другими словами, не создается таблица для представления этой связи, и поэтому значения не сохраняются.То, что я ожидал бы, является таблицей с двумя столбцами, один для "FooId" и один для "AllowedBar" и для EF для автоматического сопоставления этого с коллекцией (как это происходит со сложными типами).

Поскольку этого не происходит, мне пришлось создать класс с именем "FooAllowedBar" с двумя свойствами, которые я описал выше.

Это вызывает недовольство, потому что это единственное "соединение"Тип класса у меня есть во всем проекте.Конечно, это работает, поэтому один флажок отмечен, но кто-нибудь знает, как заставить EF сгенерировать таблицу для отношения сбора строк?(Или int, или datetime и т. Д.)

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

Большое спасибо заранее, Роб

Ответы [ 4 ]

17 голосов
/ 21 ноября 2011

EF может работать только с классами сущностей. Каждый класс сущностей должен иметь определенный первичный ключ, поэтому в вашем сценарии минимум:

public class StringData
{
    public int Id { get; set; }
    public string Data { get; set; }
}

или хуже

public class StringData
{
    [Key]
    public string Data { get; set; }
}

Теперь вы можете определить коллекцию StringData, чтобы отобразить ее как связанную таблицу:

public virtual ICollection<StringData> AllowedBars { get; set; }
3 голосов
/ 11 августа 2014

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

Условия включают в себя:

  • Список не будет длинным
  • Вам не нужно искать объекты на основе значений в этом списке

Также было бы неплохо, если бы в одной сущности было несколько списков строк, что могло бы создать много объединений.

В этих случаях я решил бы это, имея два свойства для списка. Один из них представляет собой разделенный запятыми список, используемый EF, а другой - список, который вы можете использовать при доступе к элементам списка следующим образом:

[NotMapped]
public List<String> AllowedBars { get; set; }

/// <summary>
/// Comma seperated list of AllowedBars
/// </summary>
public String AllowedBarsList
{
    get { return String.Join(",", AllowedBars); }
    set
    {
        if (String.IsNullOrWhiteSpace(value))
        {
            AllowedBars.Clear();
        }
        else
        {
            AllowedBars = value.Split(',').ToList();
        }
    }
}

Вам нужно инициализировать AllowedBars как пустой список в конструкторе.

Вам не нужно использовать атрибут [NotMapped], так как эта коллекция все равно не будет использоваться, но я думаю, что это делает намерение более ясным.

0 голосов
/ 20 ноября 2011

Вы не определили свои таблицы классов должным образом. Предположим, у вас есть две таблицы Foo и FooBar. И есть отношения один-ко-многим ч / б Foo и FooBar. Затем вы определите классы, как показано ниже.

Foo

public class Foo
{
    public int FooId { get; set; }
    public string SomeValue { get; set; }

    public virtual ICollection<FooBar> FooBars { get; set; } 
}

FooBar

public class FooBar
{
    public int FooBarId { get; set; }
    public string SomeProperty { get; set; }
    public int FooId { get; set; }

    public virtual Foo Foo { get; set; } 
}

Это создаст две таблицы с Foo, имеющим два столбца, и FooBar, имеющим 3 столбца, включая FooId, отображающий один ко многим между Foo и FooBars

0 голосов
/ 20 ноября 2011

Это не сработает. Причина этого в том, что с реляционными базами данных вы не можете реально сохранять массивы или коллекцию вещей в полях. И поскольку каждое свойство в вашем классе будет отображаться в поле базы данных, единственный способ сбора данных - это связь один ко многим. Так что вам нужно присоединиться. Так что на самом деле это не ограничение EF, а реляционных баз данных.

Есть люди, которые решают эту проблему, сохраняя XML или CSV в строковые поля в таблице. Но это считается очень плохим стилем, так что не делайте этого. Я рекомендую вам просто принять присоединение. В любом случае это никому не вредит.

...