Linq to Entity Union, генерирующий внутреннее соединение с объединенной таблицей

1

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

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

У меня есть две таблицы: OrderDetails и OrderDetailHistories. Предыстория: после определенного периода времени записи удаляются из таблицы подробностей и помещаются в таблицу историй. Поля и все точно такие же. Фактически, это объект для OrderDetailHistories:

public partial class OrderDetailsHistory : OrderDetail { }

Итак, чтобы начать, я написал небольшой тестовый запрос, который довольно хорошо отражает то, что я вижу.

var test = this.context.OrderDetails
    .Select(x => x.Descr)
    .Union(this.context.OrderDetailsHistories
        .Select(x => x.Descr))
    .Where(x => x == "wat")
    .ToList();

Что генерирует этот запрос:

SELECT 
[Distinct1].[C1] AS [C1]
FROM ( SELECT DISTINCT 
    [UnionAll1].[Descr] AS [C1]
    FROM  (SELECT 
        [Extent1].[Descr] AS [Descr]
        FROM [dbo].[OrderDetails] AS [Extent1]
        WHERE N'wat' = [Extent1].[Descr]
    UNION ALL
        SELECT 
        [Extent3].[Descr] AS [Descr]
        FROM  [dbo].[OrderDetails_History] AS [Extent2]
        INNER JOIN [dbo].[OrderDetails] AS [Extent3] ON ([Extent2].[Order_No] = [Extent3].[Order_No])
        WHERE N'wat' = [Extent3].[Descr]) AS [UnionAll1]
)  AS [Distinct1]

А? Почему этот второй оператор выбора даже ссылается на таблицу данных? Что происходит, когда я использую concat? То же самое. Перекрыть? Такое же внутреннее соединение. Хорошо, возможно, вместо того, чтобы сначала объединиться, а затем применив мое условие, я могу применить условия для каждого запроса, а затем просто объединить результаты.

Как насчет этого?

var query1 = this.context.OrderDetails.Where(x => x.Descr == "wat").Select(x => x.Descr);
var query2 = this.context.OrderDetailsHistories.Where(x => x.Descr == "wat").Select(x => x.Descr);
var result = query1.Concat(query2).ToList();

Создает почти тот же самый запрос! Кто-нибудь знает, что здесь происходит? Ожидаются ли мои ожидания?

Если я напишу.ToList() в конце вышеперечисленных запросов query1 и query2, он будет работать точно так, как я ожидал, но тогда я теряю способность делать подкачки в sql и в конечном итоге снимаю слишком много записей, когда мы 'только отображение 10 на страницу.

Любая помощь будет оценена по достоинству.

Теги:
entity-framework
linq-to-entities

1 ответ

1

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

Поэтому, если вы хотите выбрать все заказы, вы можете просто запросить OrderDetail и будут также все объекты OrderDetailsHistory:

this.context.OrderDetails
    .Select(x => x.Descr)   
    .Where(x => x == "wat")
    .ToList();

Также важно знать, как данные хранятся в вашей БД. Вы используете таблицу в классе aproach - читайте некоторые статьи об этом (например, http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table -per-type-tpt), чтобы понять, как это работает, тогда вы также поймете, почему все ваши запросы выглядят "такими странными"...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню