Dziś krótko o dwóch przydatnych czynnościach, z którymi możemy się zmierzyć w przypadku EF + LINQ.
1. Pobieranie SQL-a generowanego przez LINQ
Pracując z EF nie wiele zwraca się uwagi na generowane zapytania przez ORM. Warto jednak niekiedy podglądnąć w jaki sposób jest generowane zapytanie do bazy. Sposób który podam może także przydać się w przypadku kiedy chcemy przeprowadzić optymalizację zapytań. Aby zobaczyć wygenerowane zapytanie do bazy należy skorzystać z poniższego kodu:
Code:
using System;
using System.Data.Objects;
using System.Linq;
namespace ConsoleApplication11
{
    class Program
    {
        static void Main()
        {
            using (var contex = new AdventureWorksLT2008R2Entities())
            {
                var customer = from c in contex.Customers
                               join soh in contex.SalesOrderHeaders on c.CustomerID equals soh.CustomerID
                               join sod in contex.SalesOrderDetails on soh.SalesOrderID equals sod.SalesOrderID
                               join p in contex.Products on sod.ProductID equals p.ProductID
                               where c.CustomerID == 30113
                               select p;
                Console.WriteLine(((ObjectQuery) customer).ToTraceString());
            }
        }
    }
}
W wyniku wywołania otrzymamy następujący wynik:
Otrzymany wynik możemy bez przeszkód przekleić do ManagementStudio i wywołać.
2. Operator IN w LINQ
Przez dłuższy czas szukałem sposoby w jaki generować za pomocą LINQ zapytania do bazy z użyciem operatora IN. W końcu po przegrzebaniu internetu znalazłem prostą odpowiedź:
Code:
using System;
using System.Data.Objects;
using System.Linq;
namespace ConsoleApplication11
{
    class Program
    {
        static void Main()
        {
            using (var contex = new AdventureWorksLT2008R2Entities())
            {
                int[] customerIds = {30046, 30047, 30048, 30050, 30051, 30052};
                var customer = from c in contex.Customers
                               join soh in contex.SalesOrderHeaders on c.CustomerID equals soh.CustomerID
                               join sod in contex.SalesOrderDetails on soh.SalesOrderID equals sod.SalesOrderID
                               join p in contex.Products on sod.ProductID equals p.ProductID
                               where customerIds.Contains(c.CustomerID)
                               select p;
                string sql = ((ObjectQuery) customer).ToTraceString();
                Console.WriteLine(sql);
            }
        }
    }
}
Tak więc:
- Definiuje tablicę z wartościami które mają trafić do zapytania
- W zapytaniu sprawdzam w tablicy czy nie zawiera wartości z bazy danych
W wyniku tego zapytania otrzymuję to co chciałem czyli operator IN:
SELECT 
[Extent3].[ProductID] AS [ProductID], 
[Extent3].[Name] AS [Name], 
[Extent3].[ProductNumber] AS [ProductNumber], 
[Extent3].[Color] AS [Color], 
[Extent3].[StandardCost] AS [StandardCost], 
[Extent3].[ListPrice] AS [ListPrice], 
[Extent3].[Size] AS [Size], 
[Extent3].[Weight] AS [Weight], 
[Extent3].[ProductCategoryID] AS [ProductCategoryID], 
[Extent3].[ProductModelID] AS [ProductModelID], 
[Extent3].[SellStartDate] AS [SellStartDate], 
[Extent3].[SellEndDate] AS [SellEndDate], 
[Extent3].[DiscontinuedDate] AS [DiscontinuedDate], 
[Extent3].[ThumbNailPhoto] AS [ThumbNailPhoto], 
[Extent3].[ThumbnailPhotoFileName] AS [ThumbnailPhotoFileName], 
[Extent3].[rowguid] AS [rowguid], 
[Extent3].[ModifiedDate] AS [ModifiedDate]
FROM   [SalesLT].[SalesOrderHeader] AS [Extent1]
INNER JOIN [SalesLT].[SalesOrderDetail] AS [Extent2] ON [Extent1].[SalesOrderID] = [Extent2].[SalesOrderID]
INNER JOIN [SalesLT].[Product] AS [Extent3] ON [Extent2].[ProductID] = [Extent3].[ProductID]
WHERE [Extent1].[CustomerID] IN (30046,30047,30048,30050,30051,30052)