Я использую LINQ to SQL и Entity Framework в течение нескольких лет, и я всегда отображал свои отношения с базой данных для создания соответствующих свойств навигации. И я всегда использую свойства навигации.

Я что-то упускаю?

Если у меня есть отношение типа Category->Products один-много, я бы использовал

var redProducts = context.Category.Single(c => c.Name = "red").Products;

Я регулярно вижу людей, выполняющих ручное присоединение, по всему сайту, в проектах в Интернете и на различных других сайтах.

var employer = from category in context.Categories
               join product in context.Products
               on category.CategoryId equals product.CategoryId
               where category.Name == "red"
               select product;

Итак - почему? Каковы преимущества использования этого синтаксиса Join?

20
Kirk Broadhurst 29 Авг 2011 в 15:38

3 ответа

Лучший ответ

Обычно это ошибка.

@George прав в том, что ваши два примера функционально различны, но это не имеет ничего общего с join и не - join, однако. Но вы могли бы так же легко написать:

var redProducts = context.Category
                         .Where(c => c.Name == "red")
                         .SelectMany(c => c.Products);

... который функционально идентичен (но превосходит по удобочитаемости и удобству обслуживания) вашему примеру join.

9
Craig Stuntz 17 Апр 2018 в 02:02

Это могло произойти из-за переноса старого кода на linq2sql.

Однако эти два фрагмента кода функционально не равны.

Single вызовет исключение, а join выдает пустую коллекцию в случае отсутствия записи.

Итак, равный код без использования объединений будет:

from c in context.Categories where c.Name == "red" from p in c.Products select p;

Или

context.Categories.Where(c=>c.Name == "red").SelectMany(c=>c.Products);
4
George Polevoy 29 Авг 2011 в 12:14

Объединения, вероятно, более характерны для людей, придерживающихся реляционного мышления, а не объектно-ориентированного. Если вы думаете о своем проблемном пространстве с точки зрения, ориентированной на объект, гораздо естественнее работать с отношениями, в которых вы можете точечно перемещаться по навигации: Employee.Customers.Orders.OrderItems.OrderItem, чем иметь дело с кучей объединений. В исходном техническом документе ADO.vNext хорошо обсуждались преимущества использования модели и ассоциаций вместо объединений для работы с концептуальными моделями. К сожалению, я не могу найти этот документ на данный момент.

На мой взгляд, объединения лучше всего использовать, когда между сущностями нет естественных ассоциаций. Например, если вы пытаетесь объединить элементы по неестественным ключам (т. Е. Объединение по Customer.State и Shipping.State), вам следует использовать синтаксис объединения (или SelectMany), а не создавать ассоциации между вашими сущности в этом случае.

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

С другой стороны, навигация по ассоциациям в отношениях 1-0 .. * обычно переводится в правые внешние соединения, потому что дочерняя коллекция на законных основаниях может быть пустой, и вы захотите включить родительский элемент, даже если дочерний элемент не существует. Вы можете использовать !Any() для перехвата случаев, когда нет дочерних записей.

3
Yakimych 29 Авг 2011 в 16:15