0

У меня есть веб-приложение MVC4, где я использую LINQ.Результаты Linq отличаются от результата sql

У меня есть следующий запрос, который приводит к 53 строкам в SQL.

select * from table1 t join 
    [table2] tpf on t.TestID=tpf.TestID 
    join 
    table3 pf on tpf.Test2ID =pf.Test2ID 
    join table4 pfp on 
    pf.Test3ID = pfp.Test3ID 
    join table5 p on pfp.Test5ID = p.Test5ID where t.testtypeid=1 
    order by pfp.Test3ID,pf.Test2ID 

Если я конвертирую тот же запрос, что и ниже, он возвращает больше записей.

trvm.MyTestVMs = (
    from tt in db.table1s 
    join ttpf in db.table2s on tt.TestID equals ttpf.TestID      
    join pf in db.table3s on ttpf.Test2ID equals pf.Test2ID 

    join pfp in db.table4s on pf.Test3ID equals pfp.Test3ID 
    join p in table5s on pfp.Test5ID equals p.Test5ID 
    where tt.testtypeid == 1 

    orderby pfp.Test3ID 
    orderby pf.Test2ID 

    select new MyTestVM 
    { 
     FamilyID = pf.Test2ID, 
     ProductID = p.Test3ID, 
     Desc = p.Description 
    } 
).ToList(); 

Результат, полученный из SQL и выше LINQ, варьируется. Фактически, есть некоторый дублирующий результат, который я получаю из запроса LINQ. Что вызывает эту разницу?

+1

Учитываются ли представления базы данных или просто таблицы? Таблицы без ПК? –

+0

просто столов. первичный ключ находится в таблицах – jubi

+0

Исправьте предложение 'order by', затем измените код следующим образом:' var query = (...); '(без' ToList() 'call), затем' var sql = query. Нанизывать(); trvm.ProductFamilyProductVMs = query.ToList(); ', помещает точку останова и видит, что переменная' sql' содержит текст запроса SQL. Если да, откройте его с помощью Text Visualizer, скопируйте и вставьте его в вопрос. –

ответ

0

Оказывается, что запрос LINQ не эквивалентен запросу SQL, публикуемую в связи с использованием products переменная запроса (не показана в сообщении), которая приводит к включению одной из таблиц ссылок many-to-many в два раза, что дает больше записей.

Один из способов устранить проблему - заменить products на db.Products и применить те же фильтры, что и к переменным запроса, которые вы пытались повторно использовать.

Но если вы хотите использовать переменные запроса, то здесь правильный способ сделать это:

// Eliminate the need of DbFunctions.TruncateTime(dt) inside the queries 
dt = dt.Date; 

// Queries 

var productFamilys = (
    from tt in db.TestTypes 
    join ttpf in db.TestTypeProductFamilys on tt.TestTypeID equals ttpf.TestTypeID 
    join pf in db.ProductFamilys on ttpf.ProductFamilyID equals pf.ProductFamilyID 
    where tt.TestTypeID == TestTypeID 
    where DbFunctions.TruncateTime(pf.StartDate) <= dt 
    where DbFunctions.TruncateTime(pf.EndDate) > dt 
    select pf 
); 

var productFamilyProducts = (
    from pf in productFamilys 
    join pfp in db.ProductFamilyProducts on pf.ProductFamilyID equals pfp.ProductFamilyID 
    join p in db.Products on pfp.ProductID equals p.ProductID 
    where DbFunctions.TruncateTime(p.StartDate) <= dt 
    where DbFunctions.TruncateTime(p.EndDate) > dt 
    select new { Family = pf, Product = p } 
); 

var products = (
    from pfp in productFamilyProducts 
    select pfp.Product 
); 

var productFamilyProductVMs = (
    from pfp in productFamilyProducts 
    orderby pfp.Product.ProductID, pfp.Family.ProductFamilyID 
    select new ProductFamilyProductVM 
    { 
     ProductFamilyID = pfp.Family.ProductFamilyID, 
     ProductID = pfp.Product.ProductID, 
     ProdDesc = pfp.Product.Description 
    } 
); 

// Results 
trvm.ProductFamilys = productFamilys.ToList(); 
trvm.Products = products.ToList(); 
trvm.ProductFamilyProductVMs = productFamilyProductVMs.ToList(); 

Теперь SQL для последнего запроса (один в вопросе) выглядит следующим образом

SELECT 
    [Project1].[ProductFamilyID] AS [ProductFamilyID], 
    [Project1].[ProductID] AS [ProductID], 
    [Project1].[Description] AS [Description] 
    FROM (SELECT 
     [Extent2].[ProductFamilyID] AS [ProductFamilyID], 
     [Extent4].[ProductID] AS [ProductID], 
     [Extent4].[Description] AS [Description] 
     FROM [dbo].[TestTypeProductFamilies] AS [Extent1] 
     INNER JOIN [dbo].[ProductFamilies] AS [Extent2] ON [Extent1].[ProductFamilyID] = [Extent2].[ProductFamilyID] 
     INNER JOIN [dbo].[ProductFamilyProducts] AS [Extent3] ON [Extent2].[ProductFamilyID] = [Extent3].[ProductFamilyID] 
     INNER JOIN [dbo].[Products] AS [Extent4] ON [Extent3].[ProductID] = [Extent4].[ProductID] 
     WHERE ([Extent1].[TestTypeID] = @p__linq__0) AND ((convert (datetime2, convert(varchar(255), [Extent2].[StartDate], 102) , 102)) <= @p__linq__1) AND ((convert (datetime2, convert(varchar(255), [Extent2].[EndDate], 102) , 102)) > @p__linq__2) AND ((convert (datetime2, convert(varchar(255), [Extent4].[StartDate], 102) , 102)) <= @p__linq__3) AND ((convert (datetime2, convert(varchar(255), [Extent4].[EndDate], 102) , 102)) > @p__linq__4) 
    ) AS [Project1] 
    ORDER BY [Project1].[ProductID] ASC, [Project1].[ProductFamilyID] ASC 

т. Е. Очень похож на образец SQL-запроса и должен давать одинаковые результаты.

0

Результат другой, потому что во втором запросе у вас есть два «OrderBy», и из-за этого второй OrderBy работает над коллекцией, которая является результатом первого «OrderBy» и переупорядочивает элементы. Изменение

 orderby pfp.ProductID 
    orderby pf.ProductFamilyID 

из вашего второго запроса в

orderby pfp.ProductID, pf.ProductFamilyID 

, чтобы получить те же результаты

+0

В обоих запросах порядок - это тот же порядок по pfp.ProductID, pf.ProductFamilyID – jubi

+0

Вы используете два orderBy в своем втором запросе ... –

+0

В моем первом запросе заказывается заказ pfp.ProductID, pf.ProductFamilyID и во втором заказе pfp.ProductID orderby pf.ProductFamilyID. Какие изменения мне нужно сделать здесь – jubi

Смежные вопросы