Linq oraz Entity Framework – podstawowe polecenia i przykłady

Muszę się przyznać, że nigdy nie przepadałem za bazami danych. Zawsze uważałem je za nudny temat i nie odczuwałem większej potrzeby zajmowania się nimi. Prawdę mówiąc podobne zdanie miałem o C#, a teraz piszę w C# i uczę się Entity Framework, a w dodatku swoje doświadczenia spisuje i czasem się nimi dzielę.
Dzisiaj trochę o LINQ i Entity Frameworki, będą to raczej suche przykłady jak korzystać z linq, plus moje bardzo osobiste komentarze do nich. Przykłady pochodzą z książki, którą czytam i jeszcze nie wiem czy mogę ją polecić. Zła nie jest, ale jest w niej spora ilość błędów, które potrafią zdenerwować. Nadal jednak ją czytam, więc nie jest aż tak źle.
Entity Framework 4 in action” – bo o niej mowa, jest tworem trzech panów:
– Stefano Mostarda, – Marco De Sanctis
– Daniele Bochicchio

Książka ukazała się nakładem wydawnictwa Manning. Można ją zamówić w polskich księgarniach w cenie od 150 do 200 polskich złotych.Nie będę podawać przykładów na najprostsze zapytanie linq, zacznę od tych ciut trudniejszych, przykłady będą bazować na tych z książki
Przykłady będą się opierać na następującej bazie danych:

Oraz na takim mapowaniu jej do EDM:

Do rzeczy, czyli to co developerzy lubią najbardziej kod:

  • Grupowanie wyników na podstawie więcej niż jednego klucza jest możliwe przy pomocy nowego typu anonimowego, który posłuży za klucz do grupowania:
    1. using (var context = new OrderITEntities())
    2. {
    3.     var result = from o in context.Orders
    4.                  group o by new { o.ShippingAddress.City, o.ShippingAddress.ZipCode };
    5.  
    6.     foreach (var key in result)
    7.     {
    8.         Trace.WriteLine(string.Format(“{0}-{1}”, key.Key.City, key.Key.ZipCode));
    9.         foreach (var item in key)
    10.         {
    11.             Trace.WriteLine(item.OrderId);
    12.         }
    13.     }
    14. }

    Komentarz:
    @04 – Wyniki są grupowane na podstawie klucza {City, ZipCode}
    @06 – Najpierw trzeba przejść się po wszystkich kluczach
    @10 – Teraz można odczytać wyniki zgrupowane dla danego klucza.
    Wynikiem takiej operacji jest:

    Boston-87329
    17
    Chicago-ZipCode
    18
    city-zipc
    21
    City-ZipCode
    24
    fzxcb-xcbc
    46
    Los Angeles-34243
    31
    Los Angeles-54564
    14
    Miami-24323
    15
    Miami-34631
    16
    New York-0000001
    34
    35
    36
    New York-7777
    49
    New York-98765
    29
    30
    Rome-00100
    22
    23
    sc-sz
    32
    sdf-sdf
    47
    Seattle-24332
    13
    Seattle-98765
    12
    v<-cxv 44 Washington-98765 11 xc-dzvcx 45
  • Gdy nie potrzebna jest cała tabela, można skorzystać z projekcji wyników na nowy anonimowy typ, wybierając tylko to czego aktualnie potrzebujemy. Projekcja na przykładzie grupowania
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = from o in context.Orders
    4.             group o by o.ShippingAddress.City
    5.             into oGroup
    6.             select new { CityName = oGroup.Key, Items = oGroup };
    7.     foreach (var key in r)
    8.     {
    9.         Trace.WriteLine(string.Format(“{0}: {1}”, key.CityName, key.Items.Count()));
    10.         foreach (var item in key.Items)
    11.         {
    12.             Trace.WriteLine(item.OrderId);
    13.         }
    14.     }
    15. }

    Komentarz:
    @05 – wynik grupowania będzie w oGroup
    @06 – projekcja na nowy anonimowy typ
    @08 – pierwsza iteracja po kluczach
    @11 – kolejna iteracja po zgrupowanych obiektach
    Wyniki operacji:

    Boston: 1
    17
    Chicago: 1
    18
    city: 2
    21
    24
    fzxcb: 1
    46
    Los Angeles: 2
    14
    31
    Miami: 2
    15
    16
    New York: 6
    29
    30
    34
    35
    36
    49
    Rome: 2
    22
    23
    sc: 1
    32
    sdf: 1
    47
    Seattle: 2
    12
    13
    v<: 1 44 Washington: 1 11 xc: 1 45
  • Wybranie krotek spełniających nasze wymagania, a następnie zgrupowanie według adresu wysyłki:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var result = from o in context.Orders
    4.                  group o by o.ShippingAddress.City
    5.                      into g
    6.                      where g.Count() > 1
    7.                  select g;
    8.  
    9.     foreach (var key in result)
    10.     {
    11.         Trace.WriteLine(string.Format(“{0}: {1}”, key.Key, key.Count()));
    12.         foreach (var order in key)
    13.         {
    14.             Trace.WriteLine(order.OrderId);
    15.         }
    16.     }
    17. }

    Komentarz
    @04 – Wyniki zostaną zgrupowane na podstawia miasta
    @06 – Interesują nas tylko takie krotki, które posiadają więcej niż jedno zamówienie
    Wynik operacji

    city: 2
    21
    24
    Los Angeles: 2
    14
    31
    Miami: 2
    15
    16
    New York: 6
    29
    30
    34
    35
    36
    49
    Rome: 2
    22
    23
    Seattle: 2
    12
    13
  • Sortowanie według zadanego klucza, wykonane przez silnik DB:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var result = from o in context.Orders
    4.                  orderby o.ShippingAddress.City
    5.                  select o;
    6.  
    7.     foreach (var order in result)
    8.     {
    9.         Trace.WriteLine(string.Format(“{0}-{1}”, order.ShippingAddress.City, order.OrderId));
    10.     }
    11. }

    Komentarze
    @04 – Kluczem sortujący jest miasto
    Wynik operacji:

    Boston-17
    Chicago-18
    city-21
    City-24
    fzxcb-46
    Los Angeles-31
    Los Angeles-14
    Miami-15
    Miami-16
    New York-29
    New York-30
    New York-34
    New York-35
    New York-36
    New York-49
    Rome-22
    Rome-23
    sc-32
    sdf-47
    Seattle-12
    Seattle-13
    v<-44 Washington-11 xc-45
  • Posortowanie wyników według dynamicznie obliczanej wartości, wybranie tylko części do wyniku przy pomocy projekcji:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var result = from o in context.Orders
    4.                  where o.OrderDetails.Count > 0
    5.                  orderby o.OrderDetails.Sum(d => d.Quantity * (d.UnitPrice – d.Discount))
    6.                  select new
    7.                      {
    8.                          o.OrderId,
    9.                          o.OrderDate,
    10.                          o.ShippingAddress,
    11.                          Total = o.OrderDetails.Sum(d => d.Quantity * (d.UnitPrice – d.Discount))
    12.                      };
    13.     foreach (var item in result)
    14.     {
    15.         Trace.WriteLine(item);
    16.     }
    17. }

    Komentarze:
    @04 – Ta linia odrzuca zamówienia, które nie posiadają żadnych dodatkowych informacji, DB z którą pracuje najwyraźnie pozwala na złożenie zamówienia i nie przypisanie do niego szczegółów
    @05 – Wynik ma być posortowany, wg. nowej cechy zamówienia. Jest ona obliczania dynamicznie
    @06 – Projekcja – do wyniku zostaje dołączona informacja obliczana dynamicznie
    Wynik operacji:

    { OrderId = 16, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 1,0000 }
    { OrderId = 15, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 2,0000 }
    { OrderId = 46, OrderDate = 2010-04-20 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 4,0000 }
    { OrderId = 47, OrderDate = 2010-04-20 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 4,0000 }
    { OrderId = 21, OrderDate = 2009-02-03 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 18,0000 }
    { OrderId = 18, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 48,0000 }
    { OrderId = 34, OrderDate = 2009-10-28 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 50,0000 }
    { OrderId = 35, OrderDate = 2009-10-28 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 50,0000 }
    { OrderId = 36, OrderDate = 2009-10-28 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 50,0000 }
    { OrderId = 22, OrderDate = 2009-02-03 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 50,0000 }
    { OrderId = 23, OrderDate = 2009-02-04 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 50,0000 }
    { OrderId = 49, OrderDate = 2010-04-20 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 56,0000 }
    { OrderId = 30, OrderDate = 2009-08-09 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 90,0000 }
    { OrderId = 31, OrderDate = 2009-08-09 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 100,0000 }
    { OrderId = 12, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 100,0000 }
    { OrderId = 29, OrderDate = 2009-08-09 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 135,0000 }
    { OrderId = 13, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 152,0000 }
    { OrderId = 32, OrderDate = 2009-08-10 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 201,0000 }
    { OrderId = 17, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 254,0000 }
    { OrderId = 11, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 255,0000 }
    { OrderId = 24, OrderDate = 2010-05-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 270,2000 }
    { OrderId = 14, OrderDate = 2008-11-27 00:00:00, ShippingAddress = OrderIT.Model.AddressInfo, Total = 556,0000 }
  • Sortować można nie tylko główną tabele wyników, ale także wszystkie właściwości do których posiada ona referencje. Jest to możliwe tylko dzięki projekcji wyniku:
    1. using (var context = new Model.OrderITEntities())
    2.             {
    3.                 var result = from o in context.Orders
    4.                              select new
    5.                                         {
    6.                                             o.OrderId,
    7.                                             o.OrderDate,
    8.                                             Details = o.OrderDetails.OrderBy(d => d.Quantity)
    9.                                         };
    10.                 foreach (var item in result)
    11.                 {
    12.                     Trace.WriteLine(“oid: ” + item.OrderId + “, date: ” + item.OrderDate);
    13.                     foreach (var d in item.Details)
    14.                     {
    15.                         Trace.WriteLine(string.Format(“q:{0}, id:{1}”, d.Quantity, d.OrderDetailId));
    16.                     }
    17.                 }
    18.             }

    Komentarz: @06,07 – Wynik ma zawierać wybrane przez nas pola @08 – Details ma zawierać szczegóły dotyczące zamówienia, dodatkowo mają one zostać posortowane według ilości.
    Wynik operacji:

    oid: 11, date: 2008-11-27 00:00:00
    q:5, id:22
    q:5, id:23
    oid: 12, date: 2008-11-27 00:00:00
    q:2, id:24
    oid: 13, date: 2008-11-27 00:00:00
    q:2, id:25
    q:3, id:26
    oid: 14, date: 2008-11-27 00:00:00
    q:2, id:27
    q:5, id:28
    q:8, id:29
    oid: 15, date: 2008-11-27 00:00:00
    q:2, id:30
    oid: 16, date: 2008-11-27 00:00:00
    q:1, id:31
    oid: 17, date: 2008-11-27 00:00:00
    q:2, id:32
    q:2, id:34
    q:5, id:33
    oid: 18, date: 2008-11-27 00:00:00
    q:4, id:35
    oid: 21, date: 2009-02-03 00:00:00
    q:1, id:36
    q:2, id:37
    oid: 22, date: 2009-02-03 00:00:00
    q:5, id:38
    oid: 23, date: 2009-02-04 00:00:00
    q:5, id:39
    oid: 24, date: 2010-05-27 00:00:00
    q:1, id:69
    q:3, id:40
    q:5, id:41
    oid: 29, date: 2009-08-09 00:00:00
    q:45, id:44
    oid: 30, date: 2009-08-09 00:00:00
    q:2, id:45
    oid: 31, date: 2009-08-09 00:00:00
    q:2, id:46
    oid: 32, date: 2009-08-10 00:00:00
    q:13, id:47
    q:45, id:48
    oid: 34, date: 2009-10-28 00:00:00
    q:5, id:50
    oid: 35, date: 2009-10-28 00:00:00
    q:5, id:52
    oid: 36, date: 2009-10-28 00:00:00
    q:5, id:54
    oid: 44, date: 2010-04-20 00:00:00
    oid: 45, date: 2010-04-20 00:00:00
    oid: 46, date: 2010-04-20 00:00:00
    q:2, id:63
    oid: 47, date: 2010-04-20 00:00:00
    q:2, id:64
    oid: 49, date: 2010-04-20 00:00:00
    q:3, id:66
    q:5, id:68
  • Zwykły JOIN jest nudny 🙂 od razu przykład dla tej operacji, na 2 polach, które posłużą za podstawe łączenia tabel:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var result = from o in context.Orders
    4.                  join c in context.Companies.OfType<Customer>()
    5.                      on new { o.ShippingAddress.City, o.Customer.CompanyId }
    6.                      equals new { c.ShippingAddress.City, c.CompanyId }
    7.                  select o;
    8.  
    9.     foreach (var order in result)
    10.     {
    11.         Trace.WriteLine(string.Format(“oid:{0} date:{1} customer:{2} address:{3}”, order.OrderId,
    12.                         order.OrderDate, order.CustomerId,
    13.                         order.ShippingAddress.Address));
    14.     }
    15. }

    Komentarze
    @04 – Połączenie korzystać z klasy Order oraz Customer. Customer dziedziczy po Companies, trzeba jasno zaznaczyć, że z Companies interesują nas tylko Customer.
    @05 – Połączenia bazować będzie na nowym typie anonimowym, składającym się z City oraz ProductId
    Wynik operacji:

    oid:29 date:2009-08-09 00:00:00 customer:1 address:7th Avenue
    oid:30 date:2009-08-09 00:00:00 customer:1 address:7th Avenue
    oid:32 date:2009-08-10 00:00:00 customer:2 address:sa
    oid:34 date:2009-10-28 00:00:00 customer:1 address:2th street
    oid:35 date:2009-10-28 00:00:00 customer:1 address:2th street
    oid:36 date:2009-10-28 00:00:00 customer:1 address:2th street
  • Chciałem napisać też przykład dla OUTER JOIN, ale coś nie do końca go rozumiem. Nie chce pisać strasznych głupot. Wszystko rozbija się o użycie metody DefaultIfEmpty, nie będę niepotrzebnie wprowadzał fermentu i chaosu. Doczytam i zaktualizuje temat – obiecuje 🙂
  • W przykładach przyjęto metody TPC (Table Per Class) dla obiektów product, show oraz shirt. Przekłada się to na odpowiednie mapowanie w EF, klasy shoe oraz shirt dziedziczą po klasie product. Oczywiście tylko w C#, w sql jest to rozwiązane przy pomocy kluczy obcych. Pisząc zapytanie, które ma pobrać informację o jednym z wybranych produktów, korzystamy z dwóch tabel w sql; product oraz shoe/shirt. Linq nie jest w stanie tego samodzielnie wywnioskować, w związku z czymy należy mu w tym lekko pomóc:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var result = from p in context.Products.OfType<Shoe>()
    4.                  select p;
    5.     foreach (var product in result)
    6.     {
    7.         Trace.WriteLine(product.GetType().ToString());
    8.     }
    9. }

    Komentarz
    @03 – wybierz tylko obiekty, który są typu Shoe (będą zwracane poprzez proxy, ale dla użytkownika są one przezroczyste i korzysta się jak z normalnej klasy)
    Wynik operacji:

    System.Data.Entity.DynamicProxies.Shoe_7AA4169E6949EE79A10F953F29A44C8C07E207BD569BE65D49A2BA0AAA0A98EB
    System.Data.Entity.DynamicProxies.Shoe_7AA4169E6949EE79A10F953F29A44C8C07E207BD569BE65D49A2BA0AAA0A98EB

    Istnieje także alternatywna metoda, jest ona mniej wydajna, spełnia jednak swoje zadanie:

    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var result = from p in context.Products
    4.                  where p is Shirt
    5.                  select p;
    6.     foreach (var product in result)
    7.     {
    8.         Trace.WriteLine(product.GetType().ToString());
    9.     }
    10. }

    Komentarz
    @03 – Wybierz wszystkie obiekty Product
    @04 – Odfiltruj ze wszystkich, tylko te spełniające założenie.
    Wynik (jest taki sam jak poprzednio, znowu widać klasę proxy, jednak tym razem są to Shirt):

    System.Data.Entity.DynamicProxies.Shirt_9781A3B17068763ADD1262E9DF89ABE0B9179FD9113AA7C50B50B8F1AEE66B55
    System.Data.Entity.DynamicProxies.Shirt_9781A3B17068763ADD1262E9DF89ABE0B9179FD9113AA7C50B50B8F1AEE66B55
    System.Data.Entity.DynamicProxies.Shirt_9781A3B17068763ADD1262E9DF89ABE0B9179FD9113AA7C50B50B8F1AEE66B55
    System.Data.Entity.DynamicProxies.Shirt_9781A3B17068763ADD1262E9DF89ABE0B9179FD9113AA7C50B50B8F1AEE66B55
    System.Data.Entity.DynamicProxies.Shirt_9781A3B17068763ADD1262E9DF89ABE0B9179FD9113AA7C50B50B8F1AEE66B55
  • Może zaistnieć także sytuacja gdy potrzeba będzie znaleźć produkty danego typu, ale zwrócić jest w postaci kolekcji obiektów klasy podstawowej, na to także znajdą się dwa sposoby:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = from p in context.Products
    4.             where (p as Shoe).Sport == “Basket”
    5.             select p;
    6.  
    7.     foreach (var product in r)
    8.     {
    9.         Trace.WriteLine(string.Format(“{0}: {1}”, product.Name, product.Description));
    10.     }
    11. }

    Komentarz
    @03 – Wybierz wszystko
    @04 – Rzutuj na Shoe i spradź czy pole Sport jest równe Basket
    Wynik:

    Basket shoes: Basket shoes

    Wersja alternatywna:

    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = (from p in context.Products.OfType<Shoe>()
    4.              where p.Sport == “Basket”
    5.              select p).Cast<Product>();
    6.  
    7.     foreach (var product in r)
    8.     {
    9.         Trace.WriteLine(string.Format(“{0}: {1}”, product.Name, product.Description));
    10.     }
    11. }

    Komentarz
    @03 – Wybierz tylko Shoe
    @04 – Sprawdź warunek
    @05 – Wynik rzutuj na klasą bazową Product
    Wynik:

    Basket shoes: Basket shoes

Doszliśmy do końca zapytań i selekcji. W moich notatkach mam jeszcze małe co nie co na temat funkcji i ich wykorzystania. Dzielą się one na dwa rodzaje, te dostarczone przez EF (funkcje kanoniczne) oraz te dostarczone przez silnik bazodanowy.
Funkcje z EF:
+ działać będą z każdą bazą, która jest wspierana przez EF
– działać będą po stronie klienta
Funkcje z silnika
+ działają po stronie serwera
– silnie uzależniają od implementacji na którą się zdecydowaliśmy
Dwa przykłady:

  • Funkcja działająca w oparciu o EF
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = from o in context.Orders
    4.             where EntityFunctions.DiffDays(o.OrderDate, o.ActualShippingDate) > 5
    5.             select o;
    6.  
    7.     foreach (var order in r)
    8.     {
    9.         Trace.WriteLine(string.Format(“OrderId: {0} missing the date”, order.OrderId));
    10.     }
    11. }

    Skromy komentarz
    @04 – Jasno sprecyzowane jest, że sprawdzamy różnicę w dniach.
    Wynik operacji:

    OrderId: 11 missing the date
    OrderId: 49 missing the date
  • Identyczna funkcja, ale działająca w oparciu o DB
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = from o in context.Orders
    4.             where SqlFunctions.DateDiff(“d”, o.OrderDate, o.ActualShippingDate) > 5
    5.             select o;
    6.     foreach (var order in r)
    7.     {
    8.         Trace.WriteLine(string.Format(“OrderId: {0} missing the date”, order.OrderId));
    9.     }
    10. }

    Skromy komentarz
    @04 – Należy dodać informację o którą część daty
    Wynik:

    OrderId: 11 missing the date
    OrderId: 49 missing the date

I ostatnie czym chciałem się podzielić, to możliwość wykonania własnej kwerendy. Bez pomocy ze strony LINQ. Może się zdarzyć, że zapytanie stworzone przez LINQ będzie zbyt wolne, a samodzielnie będziemy w stanie napisać je w prostszy i bardziej wydajny sposób. Dodatkowo możliwe jest także dynamicznie zdefiniowanie parametów zapytania. Są dwa podejścia, pierwsze prostsze drugie odrobinę bardziej skomplikowane. Należy pamiętać, że nie wolno ich łączyć. Tak samo jak nie wolno kąpać gremlinów i karmić ich po północy .

  • Pierwszy przykład, to prosta kwerenda, bez szału:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = context.ExecuteStoreQuery<OrderDetailProjection>;
    4.             (“SELECT quantity, unitprice, discount FROM OrderDetail”);
    5.     foreach (var odp in r)
    6.     {
    7.         Trace.WriteLine(string.Format(“quantity:{0},discount:{1},unitprice:{2}”, odp.Quantity, odp.Discount,
    8.                         odp.UnitPrice));
    9.     }
    10. }

    Wynik:

    quantity:5,discount:0,0000,unitprice:1,0000
    quantity:5,discount:0,0000,unitprice:50,0000
    quantity:2,discount:0,0000,unitprice:50,0000
    quantity:2,discount:0,0000,unitprice:1,0000
    quantity:3,discount:0,0000,unitprice:50,0000
    quantity:2,discount:0,0000,unitprice:1,0000
    quantity:5,discount:0,0000,unitprice:50,0000
    quantity:8,discount:12,0000,unitprice:50,0000
    quantity:2,discount:0,0000,unitprice:1,0000
    quantity:1,discount:0,0000,unitprice:1,0000
    quantity:2,discount:0,0000,unitprice:1,0000
    quantity:5,discount:0,0000,unitprice:50,0000
    quantity:2,discount:2,0000,unitprice:3,0000
    quantity:4,discount:0,0000,unitprice:12,0000
    quantity:1,discount:0,0000,unitprice:10,0000
    quantity:2,discount:0,0000,unitprice:4,0000
    quantity:5,discount:0,0000,unitprice:10,0000
    quantity:5,discount:0,0000,unitprice:10,0000
    quantity:3,discount:0,0000,unitprice:3,4000
    quantity:5,discount:0,0000,unitprice:50,0000
    quantity:45,discount:0,0000,unitprice:3,0000
    quantity:2,discount:0,0000,unitprice:45,0000
    quantity:2,discount:0,0000,unitprice:50,0000
    quantity:13,discount:0,0000,unitprice:12,0000
    quantity:45,discount:0,0000,unitprice:1,0000
    quantity:5,discount:0,0000,unitprice:10,0000
    quantity:5,discount:0,0000,unitprice:10,0000
    quantity:5,discount:0,0000,unitprice:10,0000
    quantity:2,discount:1,0000,unitprice:3,0000
    quantity:2,discount:1,0000,unitprice:3,0000
    quantity:3,discount:0,0000,unitprice:2,0000
    quantity:5,discount:0,0000,unitprice:10,0000
    quantity:1,discount:0,0000,unitprice:10,0000
  • Teraz kwerenda z możliwością parametryzacji zapytania, wersja prostsza dynamicznego dodawania wartości dla zapytania. Jest identyczna jak w wywołaniu WriteLine(…):
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var r = context.ExecuteStoreQuery<string>
    4.             (“SELECT Name FROM company WHERE ShippingCity={0} AND billingcity={1}”, “New York”, “paris”);
    5.  
    6.     foreach (var name in r)
    7.     {
    8.         Trace.WriteLine(name);
    9.     }
    10. }

    Wynik:

    Billl Clay
  • Oraz wersja ciut trudniejsza, z wykorzystaniem paramentów ściślej związanych z bazą danych:
    1. using (var context = new Model.OrderITEntities())
    2. {
    3.     var a = new SqlParameter(“p0”, DbType.String) { Value = “New York” };
    4.     var b = new SqlParameter(“p1”, DbType.String) { Value = “Paris” };
    5.     var r = context.ExecuteStoreQuery<string>
    6.            (“SELECT name FROM company WHERE shippingcity= @p0 AND billingcity= @p1”, b, a);
    7.     foreach (var name in r)
    8.     {
    9.         Trace.WriteLine(name);
    10.     }
    11. }

    Wynik:

    Billl Clay

To na razie tyle. Myślę, że wyskrobię jeszcze kilka wpisów dotyczących DB i EF. Przypominam także, że moje wpisy nie są idealne i mogą zawierać błędy. Także nie trzymałbym się tak bardzo kurczowo tego co napisałem. Najlepiej będzie, jeśli sami spróbujecie czy to co napisałem działa oraz popróbujecie zmodyfikować kod, który jest tutaj przedstawiony.
Jak zawsze chętnie przyjmę na klatę wszystkie komentarze, którymi tak chętnie się ze mną dzielicie 😉
Jarek