Jeg velger å starte med vårt forretningslag for å gå rett på sak når det gjelder LINQ Methoder og syntaks
Den første metode jeg vil vise er den enkleste, den henter samtlige poster fra Produkt tabellen i NorthWind eksempel databasen til Microsoft og vi får vist enkel link syntaks og metodikk.
Metoden her henter en generisk liste av typen IEnumerable<Product>. Product er autogenerert av ORM generatoren i Visual Studio 2008 når vi drar og slipper databasetabellen til en .dbml designerflate. dbml fila finnes som mal i Visual Studio 2008 Vi kommer tilbake til hvordan dette gjøre senere men jeg vil bare kort si at ORM generator har full støtte for relasjoner i databasen og genererer kode og klasser med riktig relasjonsoppsett i forhold til de tabellene vi drar og slipper inn på designeren.
Metoden vår sender også ut en streng med navnet på listen slik at vi kan bruke denne til for eksempel tittel på en webside eller en label for en visning.
public static IEnumerable<Product> GetAllProducts(
out string DataListTitle)
{
OrdersDataContext db = new OrdersDataContext();
var products = from p in db.Products
select p;
DataListTitle = "Alle produkter";
return products;
}
OrdersDataContext brukes til å instansiere alle objektene i vår dbml fil deriblant Product objektet, vi lager først en ny instans av denne slik:
OrdersDataContext db = new OrdersDataContext();
Vi har nå tilgang til alle objekter, hendelser og methoder via OrdersDataContext instansen og bruker de nye SQL lignende nøkkelordene "from", "select og "in" i neste utrykk:
var products = from p in db.Products
select p;
Vi har nå lagt en sterkt typet variabel products som er en generisk enumerator av produkter (IEnumerable<Product>) idet Parameteret db.Products returnerer denne datatypen vet kompilatoren og intellisense at var products er av denne typen. variabelen p er også satt til typen Product, altså et enkelt produkt. Variabel p blir ikke brukt i denne omgang idet vi bare vil lese inn hele tabellen i vår products (IEnumerable<Product>) variablel.
Vi tildeler utparameteret verdien "Alle produkter":
DataListTitle = "Alle produkter";
Og returnerer til slutt vår products (IEnumerable<Product>) variablel ved å si:
return products;
Og vips vi har skrevet og forhåpentligvis forstått vår hallo verden metode i LINQ sammenheng.
På Fredag kommer forklaringen på neste metode, i mellomtiden kan du jo kose deg med en fullstendig listing av Products klassen:
using System;
using System.Linq;
using System.Collections.Generic;
using Dal;
/// <summary>
/// Ordre klassen vår fungerer som et forretningslag mellom Ordres.dbml
/// og presentasjonslaget. Dette gir oss mulighet å styre tilgangen til
/// databasen samt å tilrettelegge data for presentasjon og validere
/// inndata. I dette eksempelet gjør vi ikke mye av det men følger for
/// ordens skyld god praksis.
/// </summary>
public class Products
{
/// <summary>
/// Henter samtlige produkter i basen
/// </summary>
/// <param name="DataListTitle">En meldinggsstreng som
/// blir returnert i tillegg til IEnumerable[Product]</param>
/// <returns>IEnumerable[Product]</returns>
public static IEnumerable<Product> GetAllProducts(
out string DataListTitle)
{
//Først henter vi DataContext
OrdersDataContext db = new OrdersDataContext();
//Vi bruker det nye nøkkelordet "var" som får sin type ved
//kompilering, ikke ved kjøretid og er derfor en sterkt
//typet variabel.
//Her ser vi et enkelt eksempel på en LINQ select.
//Legg merke til likheten til SQL og at du har intellisense.
var products = from p in db.Products
select p;
DataListTitle = "Alle produkter";
return products;
}
/// <summary>
/// Henter alle produkter i en kategori fra basen
/// </summary>
/// <param name="categoryName">Produkt kategorien
/// vi ønsker å filtrere på</param>
/// <param name="DataListTitle">En meldinggsstreng som
/// blir returnert i tillegg til IEnumerable[Product]</param>
/// <returns>IEnumerable[Product]</returns>
public static IEnumerable<Product> GetProductsByCategory(
string categoryName,
out string DataListTitle)
{
//Igjen henter vi DataContext
OrdersDataContext db = new OrdersDataContext();
//Vi bruker det nye nøkkelordet "var" som får sin type
//ved kompilering, ikke ved kjøretid og er derfor en
//sterkt typet variabel. Denne gangen filtrerer vi med
//en where klausul og sorterer på Produkt Navn.
var products = from p in db.Products
where p.Category.CategoryName ==
categoryName
orderby p.ProductName
select p;
DataListTitle = "Alle produkter i " + categoryName +
" kategorien";
return products;
}
public static void Insert(
Product product, out string DataListTitle)
{
OrdersDataContext db = new OrdersDataContext();
db.Products.InsertOnSubmit(product);
db.SubmitChanges();
DataListTitle = "Produktet ble lagt til";
}
public static void Insert(
string productName,
decimal unitPrice,
short unitsInStock,
short unitsOnOrder,
out string DataListTitle)
{
Product p = new Product();
p.ProductName = productName;
p.UnitPrice = unitPrice;
p.UnitsInStock = unitsInStock;
p.UnitsOnOrder = unitsOnOrder;
p.Discontinued = false;
Insert(p, out DataListTitle);
}
public static void Save(
Product product, out string DataListTitle)
{
OrdersDataContext db = new OrdersDataContext();
Product prod =
db.Products.Single(
p => p.ProductID == product.ProductID);
prod.ProductName = product.ProductName;
prod.UnitPrice = product.UnitPrice;
prod.UnitsInStock = product.UnitsInStock;
prod.UnitsOnOrder = product.UnitsOnOrder;
prod.Discontinued = product.Discontinued;
db.SubmitChanges();
DataListTitle = "Produktet ble oppdatert";
}
public static void Save(
int productId,
string productName,
decimal unitPrice,
short unitsInStock,
short unitsOnOrder,
bool discontinued,
out string DataListTitle)
{
OrdersDataContext db = new OrdersDataContext();
Product p = new Product();
p.ProductID = productId;
p.ProductName = productName;
p.UnitPrice = unitPrice;
p.UnitsInStock = unitsInStock;
p.UnitsOnOrder = unitsOnOrder;
p.Discontinued = discontinued;
Save(p, out DataListTitle);
}
/// <summary>
/// Denne metoden sletter produktet eller merker det som
/// discontinued. Vi viser et eksempel på en mer menigsfull
/// forretningslogikk i denne ene metoden for å
/// anskueliggjøre at dette er forretningslaget for evt.
/// nybegynnere blandt våre lesere.
/// </summary>
/// <param name="productId">Produkt Id</param>
/// <param name="DataListTitle">utdata streng</param>
public static void Delete(
int productId, out string DataListTitle)
{
OrdersDataContext db = new OrdersDataContext();
DataListTitle = "Produktet ble slettet";
Product product =
db.Products.Single(p => p.ProductID == productId);
//Vi skjekker om Produktet befinner seg i en ordre
//før vi eventuellt sletter produktet
if (product.Order_Details.Count <= 0)
{
//produktet finnes ikke i noen ordre,
//der er ok å slette det.
db.Products.DeleteOnSubmit(product);
}
else
{
//Produktet finnes i en eller flere ordrer, på grunn av
//relasjonene mellom ordre og produkt samt av gjengse
//regnskapsmessige årsaker kan det derfor ikke slettes.
//Vi setter istedet Product.Discontinued til sann slik
//at vi kan filtere produktet bort i ulike visninger.
DataListTitle = "Produktet fantes i en ordre." +
" Ble derfor merket som Discontinued (føres ikke)" +
" istedet for å slettes";
product.Discontinued = true;
}
//Her bruker vi strukturert unntaks håndtering som et
//eksempel på hvordan det kan gjøres.
//For unntakstilfellet hvor en ordre er lagt til etter at
//vi skjekket om produktet eksisterte i en bestående ordre.
try
{
db.SubmitChanges();
}
//Vi fanger først inn den mest forventede feilkilde
catch (System.Data.SqlClient.SqlException e)
{
//Vi skjekker at feilmelsingen inneholder
//melding som forventet
if (e.Message.Contains(
"The DELETE statement conflicted with the REFERENCE"))
{
DataListTitle = "Produktet kunne ikke slettes fordi " +
"ordrer inneholder referanse til dette produktet";
}
else
{
//Feilen var likevel uforventet.
DataListTitle =
"En ukjennt feil oppsto, kontakt systemansvarlig";
}
}
//Dersom et uforventet generisk unntak oppsto melder vi
//fra om dette via vår utdata streng og kaster et unntaket
//videre til metoden som kallte denne methoden.
catch (Exception e)
{
DataListTitle = "En ukjennt feil oppsto";
throw (e);
}
}
}