Как эффективно установить коллекцию EntityCollection «многие ко многим» в Entity Framework? - PullRequest
2 голосов
/ 30 мая 2011

Когда Entity Framework генерирует ObjectContext для двух таблиц базы данных (скажем, Table1 и Table2), связанных с таблицей отношений «многие ко многим», он не создает объект для таблицы внешних ссылок, выбирая вместо этого свойства коллекции для любой конец отношений. Таким образом, в таблице 1 у вас есть EntityCollection<Table2> Table2s, а в таблице 2 у вас есть EntityCollection<Table2> Table1s. В большинстве случаев это действительно здорово ...

Однако в этом сценарии у меня есть список целых чисел, которые представляют идентификаторы базы данных строк Table2, которые должны быть в коллекции Table1.Table2s.

Я не вижу способа просто установить эту коллекцию, используя ключи сущностей, поэтому я застрял, выбирая их в ObjectContext, а это уже тонна работы без всякой причины. Я позволю себе надеяться, что LINQ-to-Entities будет интеллектуально откладывать выполнение и выполнять все это на SQL-сервере так, как мне бы хотелось (хотя мое «Где используется» содержит, которое может или не может быть корректно переведено в IN () в SQL). Так что я могу пойти так далеко, как:

table1instance.Table2s.Clear();
var table2sToInclude = context.Table2s.Where(
  t => 
  listOfTable2DatabaseIds.Contains(t.Id));

Но нет EntityCollection<T>.AddRange(IEnumerable<T>) или чего-либо еще, и, конечно, нет метода расширения IEnumerable<T>.ToEntityCollection<T>(), поэтому я не знаю, что делать с этими результатами на данный момент. Все, что я могу сделать, это

foreach (var table2 in table2sToInclude)
{
  table1instance.Table2s.Add(table2);
}

, что кажется смешным, и я знаю, что это вызовет много ненужных оценок.

Есть ли "правильный" или, возможно, "менее отстойный" способ сделать это?

1 Ответ

2 голосов
/ 31 мая 2011

Нет EF не будет откладывать выполнение любого запроса.Там нет ничего, как вставить из выбора.Linq-to-entity - это просто язык запросов, и ответственность за его выполнение заключается в выполнении.Он строго отделен от функций персистентности, предлагаемых самим EF.

Если вы хотите создать отношения между существующим элементом из таблицы1 и выходом из таблицы из таблицы2, вы можете использовать код, подобный следующему:

using (var ctx = new YourContext())
{
    var table1 = new Table1 { Id = 123 };
    ctx.Table1s.Attach(table1);

    foreach (var table2 in table2sToInclude.Select(id => new Table2 { Id = id }))
    {
        ctx.Table2s.Attach(table2);
        order.Table2s.Add(table2);
    }
    ctx.SaveChanges();
}

Этот код создает связь между элементом Table1 с идентификатором 123 и всеми элементами Table2 из table2sToInclude без загрузки какой-либо отдельной записи из базы данных.

Что делает добавление записей по одной "хромой"?Вы понимаете, в чем выгода AddRange?AddRange в типичной коллекции расширяет емкость внутреннего массива и просто копирует элементы в расширенный массив.EntityCollection не является типичным массивом и должен обрабатывать каждую добавленную сущность.Таким образом, даже если будет AddRange, он будет внутренне повторять элементы и обрабатывать их по одному.

...