IronRuby 1.1 with LINQ support

by DotNetNerd 20. July 2010 08:37

Finally LINQ is supported in IronRuby now from v. 1.1 and I think it has been solved quite elegantly without any real syntactical gooeyness. Trying it out has been made very straight forward by looking at the 101 LINQ samples rewrite for IronRuby.

From day one LINQ has seemed a natural fit with IronRuby already having a similar approach with functions such as .each {|item| ...} which is accessible on anything that can be enumerated - very much like a big part of LINQ is extentions methods to the IEnumerable interface. No doubt there has been some challanges around how to map generics, extention methods etc between the languages, but syntactically it seems a natural fit.

products.where(lambda { |p| p.units_in_stock > 0 and p.unit_price > 3.00 }).each { |x| puts x.product_name }

Combining functional methods from LINQ with the existing Ruby methods just makes the "Integrated Query" syntax even better. So now we get a .each method with LINQ even though Microsoft originally didn't want to include it :)

 

Tags: ,

Repository design med LINQ – querying

by DotNetNerd 23. May 2009 18:38

Linq implementationer rettet imod databaser har gjort der nemt tilgængeligt at anvende lazy loading og at opbygge querys via komposition. “With great power comes great responsibility” fristes jeg til at skrive, da den meget integrerede brug af lazy loading gør at man skal huske selv at overveje hvornår querys skal omsættes til SQL og afvikles imod databasen. Det har udviklet sig til et best practice råd i MVChvor det direkte bryder med MVC mønstret idet man flytter logik til viewet – hvilket naturligvis kan være et lige så stort problem i andre framework.

I forlængelse af diskussionen omkring hvornår querys afvikles giver Linq anledning til at overveje hvordan man vil indkapsle sine querys? Den før omtalte Repository is dead: Long live repositoryblogpost omhandler netop diskussionen om man skal have en metode pr query eller om selve filtreringen er et argument der passes til metoder som T FindOne(Expression<Func<T, bool>> expression). Kort og sagt med andre ord er argumenterne for hver indkapsling vs Open Close Principle.

Indkapsling og dermed også genbrug af querys anser jeg ihvertflad som vigtigt, men der er andre måder at gøre det på end ved at lave et repository med “en metode pr. query”. Den første tanke er tit at man kan lave en service ovenpå sine repositories som indeholder querylogikken. Det vil imidlertid betyde at en sådan service blot bliver et gennemstillingslag for simple querys – og det er kode jeg ikke kender nogen der synes er sjovt at skrive.

Filtre som extention methods en elegant måde at skrive querys der kan genanvendes og skabes via komposition ved hjælp af piping f,eks new Repository<Customer>().FindAll().WithAddress(adr).WithNumberOfChildren(2); Som altid er der imidlertid “no such thing as a free dinner”, da det ikke sikrer at querys bliver afviklet. Her er min konklusion indtil videre at jeg vil vise tilbage til den tidligere nævnte best practice, og lade det være udviklerens ansvar.

 

Tags:

Repository design med LINQ – object-relational mappers

by DotNetNerd 10. May 2009 14:25

Object-Relational Mappers eller bare ORM’s er værktøjer der håndterer det at mappe imellem relationelle data i en database til objekter som vi gerne vil arbejde med dem (og tilbage igen naturligvis). Der findes efter hånden et hav af forskellige ORM eller ORM-lignendene værøtøjer hvor nogen af de mest udbredte er SubSonic, LightSpeed, NHibernate, LINQ to SQL og LINQ to Entities.

Personligt er det de 3 sidstnævnte jeg hovedsageligt har erfaring med, og hvor NHibernate er det jeg primært anvender idag. Der er mange ting at vurdere når man vælger et ORM, men det der normalt afgør ens valg er kompatibilitet med andre teknologier, hvor “tungt” frameworket er og hvor fleksibelt det er. Med fleksibilitet menes her normalt hvordan man kan beskrive sine mapninger og hvilke typer mapninger der er mulige. Det er eksempelvis ikke alle der understøtter mange-til-mange relationer.

Som helt kort guideline vil jeg idag anbefale NHibernate hvis man skal have mest mulig fleksibilitet, LINQ to Entities hvis man vil have best mulig kompatibilitet med .NET teknoligier (især kommende teknologier) og en af de sidst hvis man gerne vil have et mere letvægts ORM der er let at gå til.

Jeg skal muligvis passe på med at kalde LINQ to SQL/Entities for ORM’s, da især Microsoft argumenterer for at de er noget lidt andet. De fleste anser dem dog som ORM’s, og jeg vil også argumentere for at det er hvad produktet er “at it’s core”.

En anden udbredt misforståelse er at LINQ i sig selv er en database teknologi og har noget med et ORM at gøre. Det er imidlertid forkert, da LINQ udelukkende som navnet (Language INtegrated Query) antyder er et sprog til at skrive querys imod en eller anden for for datastore. LINQ providerne til SQL/Entities udgør imidlertid hvad jeg vil kalde ORM’s, da de netop håndterer mapning og persistering af data i databaser.

Der findes en version af LINQ to NHibernate, som efter min mening giver den bedste blanding af et gennemprøvet og fleksibelt modelleringsværktøj i NHibernate, sammen med et lækkert query sprog i LINQ. Til komplekse querys har det imidlertid stadig nogle fejl og mangler, så træerne vokser ikke ligefrem ind i himlen.

En af de ting der bliver talt en del om idag, og som især LINQ to SQL/Entities bliver kritiseret for ikke at give er en Persistence Ignorent domænemodel.

“Persistence ignorance (PI) is a property of "ordinary classes where you focus on the business problem at hand without adding stuff for infrastructure-related reasons.”

Det vil sige om man skal skrive kode i selve modellen der beskriver hvordan objekterne mappes, og om valget af ORM stiller nogen krav til ens øvrige kode.

PI er især et fokusområde for agile udviklere, og det er heldigvis et område Microsoft har fået øjnene op for, således at de har arbejdet på at opnå PI med LINQ to Entities i v2. Lige som afsluttende bemærkning kan jeg nævne at successen med at implementere det nok kommer til at afgøre mit valg af ORM fremover.

disco%20orm1

Tags: ,

Repository design med LINQ

by DotNetNerd 3. May 2009 13:19

Repositories er omdrejningspunktet i de fleste webapplikationer, og et godt repository design er derfor vigtigt. Jeg tror de fleste har prøvet at fortryde et designvalg i forhold til repositories og tænkt “why didn’t I take the blue pill”.

Da jeg startede som udvikler lærte jeg, ligesom så mange andre, at bygge et dataaccess lag hvor man typisk havde en klasse der håndterede adgang til en enkelt tabel i databasen. Det betød at database designet leakede ud i hele applikationen som blev databasedrevet. Sidenhen er ORM’s og DDD blevet mere udbredt og PI (Persistence Ignorance) tilstrebes. Samtidig er LINQ blevet den foretrukne måde at udtrykke querys på, hvilket giver en række nye design muligheder/beslutninger.

Derudover er der forskellige “skoler” med hensyn til om man mener querys bør indkapsles i et repository, eller om de skal ses som en del af ens business logic, og måske ligefrem være fuldgyldige objekter. Transaktioner og validering har desuden stor indflydelse på hvordan det kan være hensigtsmæssigt at designe sit repository - og hvordan det samlede design har indvirkning på hvordan applikationen struktureres.

For nylig læste jeg så en række blogposts der kan findes via CodeBetter’s “Reposptiry is dead: Long live repository”, hvor der netop blev diskuteret repository design, hvilket fik mig til også at tænke en ekstra gang over designet i mit nuværende projekt. Med udgangspunkt i de ting vil jeg derfor skrive en lille serie posts om emnet, hvor jeg i vilkårlig rækkefølge vil se på emner som:

  • DDD principper
  • Object-Relational Mappers
  • Repositories som singletons
  • Querying: fleksibilitet og indkapsling
6644The_red_pill_or_the_blue_pill

Tags: , ,

Technology overflow

by DotNetNerd 21. January 2009 19:24

Nye frameworks, tools og principper

Starten på det nye år, som samtig har været starten på nyt job for mig, har betydet at det var tid til at lære nogle frameworks at kende som jeg ikke tidligere har brugt professionelt. Det har været rigtigt spændende, men har også fået mit hoved til at eksplodere i forhold til tanken om at skulle blogge om det. Jeg vil derfor skrive lidt om hvad jeg har set på, fordi det nok er en del af de ting bloggen kommer til at omhandle fremadrettet.

Vi er en shop der gør alvor af at arbejde efter agile pricipper så jeg har haft tid til at kigge på ORM, Unit testing, mocking, Dependency Injection, Continuous Integration og Migrations. Dertil kommer Office Interop og ASP.NET MVC, som jeg endelig får mulighed for at bruge professionelt, hvor det ellers har været på todo-listen hjemme siden jeg fik leget med de helt tidlige bits. Og sidste men ikke mindst har jeg kigget op tools til synkronisering og deling af data.

Object relationel mappers

Mere præcist har jeg i forbindelse med ORM's kigget på NHibernate, Fluent NHibernate og LINQ to NHibernate, samtidig med at jeg har en bog på vej om LINQ to entities. Jeg håber LINQ to Entities udvikler sig til et reelt alternativ til NHibernate, som jeg lige knap synes det er idag. Hovedanklagen idag er at det ikke giver persistence ignorence, hvilket er et stort minus i forhold til at få et pænt løst koblet design. Det er dog et issue Microsoft er klar over, og noget de arbejder på til vNext. Et andet issue der arbejdes på som er væsentligt er iøvrigt model drevet design, hvor LINQ to Entities idag er meget datadriven.

Continuous Integration

Opsætning af et continuous integration miljø, som skal baseres på Team Foundation Server er en anden ting jeg er ved at se på. Umiddelbart virker det nemt at komme igang med, men udarbejdning af build scrips skal nok blive interessant at se på. En overvejelse er blandt andet om man skal holde sig til at bruge MS Build Server eller om NAnt viser sig at være den rigtige vej at gå?

Migrations

Migrator.NET har været rimeligt nemt at komme igang med, bortset fra at dokumentationen er rimeligt tynd, så selve konfigurationen skulle det lige pilles lidt ved for at få det til at spille.

Data synkronisering og deling af data

Idet jeg er begyndt at pendle er synkronisering af data imellem min desk- og laptop også blevet et super relevant emne, hvilket fik mig til at afprøve synctoy, live sync, mesh, skydrive samt servicen delicious. Mesh har jeg forelsket mig lidt i, selvom jeg må erkende at stabiliteten ikke er god nok endnu i beta versionen, samtidig med at de 5 GB plads man får idag er lidt tyndt når man på et skydrive får 25 GB.

LINQ extensions - nogen ideer til hvad vi mangler?

by DotNetNerd 31. October 2008 11:32

En af de rigtigt fede ting ved LINQ er at det er så nemt at udvide, så jeg troede egentlig det ville vælte frem med extension librarys. Der er da også kommet nogen stykker man kan finde rundt omkring, men ikke gået så stærkt som jeg egentlig ville tro. Jeg overvejer derfor selv at begynde at lave et med nogle af de helt oplagte, som man ofte står og mangler med udgangspunkt i at extende IEnumerable<T>. Fra dag ét undrede jeg mig f.eks over at der ikke findes en ToCollection i samme stil som ToList? Nu jeg roder med Silverlight er ToObservableCollection også en der springer i tankerne?! Og i god funktionel stil undrer man sig også umiddelbart over at der ikke er en foreach, men det viser sig at være fordi VB ikke kan håndtere statement lambda udtryk. Det vil sige at man eksempelvis ikke kan skrive nedenstående - da det ikke returnerer en værdi.

function(p) Response.Write(p.Name) 

Statement lambda expressions virker imidlertid i C#, så den ryger stadig med i listen over metoder jeg gerne vil have med, især da den er helt oplagt at "låne" her. Klassen der kan hentes via linket indeholder desuden også er andre interessante extensions eksempelvis til at generere sequences ud fra algoritmer/enumerators og til at skrive pretty formated strings ud fra collections. Sidstnævnte kunne iøvrigt passende laves sammen med Scott Hanselmans "Pure evil ToString"

Diverse extensions til serialisering synes jeg også virker oplagte, omvend jeg nok vil ligge dem separat således at man ikke altid får dem med hvis man vil bruge de andre - ToJSON, ToYAML, ToXml, ToBinary osv springer mig umiddelbart i tankerne som muligheder? Hvis du ellers sidder med en god ide til hvad der mangler i standard pakken, så skriv endelig for jeg tager gerne imod forslag, da det kunne være interessant at lave en pakke andre også har gavn af.

Tags:

LINQ - Language Integrated Query

by DotNetNerd 10. May 2007 16:32

LINQ - Language Integrated Query.

LINQ som er den store nyskabelse i .NET 3.0 står for Language Integrated Query. Idéen er at skabe et querysprog som er generelt anvendeligt uanset hvilken type data der er tale om, og at gøre querys til "first class citizens" som Anders Hejlsberg ynder at udtrykke det. Med andre ord vil det sige at querys skal væk fra at være noget man skjuler i et datalag og op hvor de hører hjemme som en naturlig del af logikken. Derudover for man compile time type checking og intellisence da det ikke blot er strenge man arbejder med.

Som udgangspunkt findes der 3 datadomæner der udgør 5 typer som LINQ kan arbejde med, men lige som med alt andet i .NET er det naturligvis muligt at lave sine egne klasser til at håndrere andre former. .NET shippes med support for LINQ to Objects, LINQ to XML, LINQ to SQL, LINQ to DataSet og LINQ to Entities.

LINQ basics.

LINQ kan arbejde med alt der implementerer IEnumerable<T>, da det giver mulighed for at data kan traverseres sekventielt. Klasserne til at behandle sekventielle querys findes i System.Query.Sequence.

Funktioner, som where, from, select, union osv. er defineret som extension methods (se evt artikel om .NET 3.5 og Orcas), med en høj grad af inferens sådan at de kan bruges som udtryk uden at alle typer skal specificeres minutiøst. Inferens er vigtig for kodens læsbarhed da man derved kan skrive "from c in customers" uden at skulle skrive specifikt at c er af typen Customer.

IQueryable<T> arver fra IEnumerable<T> og tilføjer på overfladen blot de to metoder CreateQuery<T> og Execute<T>, men det er dem der gør det muligt at bygge et expression tree ved hjælp af klasserne i System.Query.Queryable og afvikle det som et query imod sine data. Det er derved muligt at lave optimerede og dynamiske querys hvis det skulle være nødvendigt. Det er denne type optimerede querys vi omtaler som LINQ to SQL, LINQ to XML osv. som er rettet imod at lave effektive querys imod specifikke datakilder.

LINQ to Objects.

I forbindelse med querys imod objekter for man mulighed for at finde frem til objekter med bestemte egenskaber på en pænere måde end man traditionelt kan idet man er nød til at skrive loops inden i loops for at gennemløbe hirakisk struktureret data.
Et simpelt eksempel som du kan se her viser syntaksen for hvordan man i en liste af customers kan finde customers der kommer fra en by der starter med bogstavet "O".

IEnumerable<Customer> list = from customer in customers
                                where customer.City.StartsWith("O")
                                select customer;

Men udover de helt banale metoder til at filtrere data er der en række metoder til f.eks. at lave unions, paging, order by, returnere resultatet som List eller Array osv. Her et et eksempel hvor den 3 og 4 customer hvis navn starter med "C" i 2 collections returneres sorteret efter navn som en Liste der bruges som argument til instantieringen af en Collection<Customer>.

Collection <Customer> list = new Collection<Customer>(
                                         (from customer in customers.Union(customers2)
                                          where customer.Name.StartsWith("C")
                                          orderby customer.Name
                                          select customer).Skip(2).Take(2).ToList());


LINQ to XML.

LINQ to XML giver naturligvis de samme muligheder for at skrive querys og udtrække de data man har behov for. Udover det følger der en række klasser med der bruges til at arbejde med XML, og disse kan genkendes ved at de er prefixet med X. Her er et eksempel på hvordan man kan bygge et simpelt xml dokument.


XElement element = new XElement("contacts",
                               new XElement("contact", new XAttribute("name", "Christian")),
                               new XElement("contact", new XAttribute("name", "Mia")));

VB får faktisk mulighed for at gøre dette endnu enklere, idet xml'en kan skrives direkte inline. Herefter vil compileren automatisk generere kode som i ovenstående eksempel.

Når man så enten har bygget eller loadet sit xml fra en fil kan querys laves med følgende syntaks:

var names = from el in element.Descendants("contact")
            where el.Attribute("name").Value.StartsWith("C")
            select el.Attribute("name");

LINQ to SQL || LINQ to Entities || LINQ to Dataset.

LINQ to SQL og LINQ to Entities er til at arbejde med data fra en database, men derudover shippes også LINQ to Dataset til at lave querys imod disconnectede data. LINQ to SQL og Entities fungerer ved at man designer en mapningsstruktur lidt på samme måde som ved brug af strongly typed datasets. Editoren til at gøre dette kan undværes, da der er også er et commandline tool ved navn sqlmetal. Det er muligt ved hjælp af switchen "/sprocs" af få genereret metoder til at bruge stored procedures.

sqlmetal /server:localhost /database:AdventureWorks /user:username
/password:password /sprocs /code:AdventureWorks.cs

En overordnet måde at se denne slags mapning på er:

Database -> DataContext
Table -> Class
Column -> Property
Stored Procedure -> Method

LINQ to Entities bygger på Entities frameworket som er en del af ADO og er et superset af den funktionalitet LINQ to SQL tilbyder. Det er derved muligt at lave en logisk model oven på sin database, og arbejde med arv, mange-til-mange relationer og sammensatte klasser bestående af værdier fra forskellige tabeller i databasen. Alternativt kan man arbejde med LINQ to SQL der er mere simpelt, og så enten binde direkte til datasources, eller lave sin egen mapning af objekter.

Når LINQ kommer kan man altså enten arbejde direkte med data eller bruge en container i form af datasets eller entities.

For at give et indtryk af hvordan man arbejder med databaser er her en række eksempler.

Et typisk eksempel på et query imod et dataset kan så se ud som sådan:

var query = from dataRow in ds.customerTable.AsEnumerable()
            where r.Field<string>("LastName") == "Nielsen"
            select r.Field<string>(“FirstName”);


Ligeledes vil et query der returnerer autogenererede custom entities se sådan ud:

Databases.MyDB db = new Databases.MyDB(connectionString);

var nameList = from c in db.Customers
               join a in db.Adresses
               on c.AdressID equals a.ID
               orderby c.Name
               select new Customer{Name = c.Name};         

     
Sidst men ikke mindst skal man jo også kunne submitte ændringer tilbage til databasen. Dette er så enkelt som det kan være, så jeg vil lade et insert og delete kodeeksempel tale for sig selv.

MyDB db = new MyDB(connection);
  Customer c = new Customer();
  c.Name = "Luffe";
  Customer c2 = new Customer();
  c2.Name = "Ole";
  db.Customers.Add(c);
  db.Customers.Remove(c2);
  db.SubmitChanges();

Som man næsten kan gætte er updates lige så enkle, men for god ordens skyld er her et eksempel.

var customer = db.Customers.Single( c => c.Name == "Bo" );
customer.Name = "Ib";
db.SubmitChanges();

Dynamiske querys.

Til lidt mere advanceret brug er det også muligt at bygge sine querys dynamisk. Det følgende eksempel viser hvordan man eksempelvis kan konstruere et query der finder Customers fra Odense.
IQueryable queryable = customers.ToQueryable();

ParameterExpression parameter = Expression.Parameter(typeof(Customer), "c");

Expression body = Expression.EQ(
    Expression.Property(parameter, typeof(Customer).GetProperty("City")),
        Expression.Constant("Odense"));

LambdaExpression predicate = QueryExpression.Lambda(body, parameter);

Expression where = QueryExpression.Where(queryable.Expression, predicate);

queryable = queryable.CreateQuery(where);

 

Tags: , , , ,

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List