"The noblest pleasure is the joy of understanding"   (Leonardo da Vinci)
Website banner

Archive for the ‘C#/ASP’ Category

[C# Talk] : Query re-use in Linq To SQL

Sunday, November 29th, 2009

Har du også overvejet om mulighederne for query re-use i Linq To SQL? Det vil sige det at man kan genbruge dele af sine Linq To SQL queries, ved at laegge dem ud som properties i sine
datamodel-klasser.

Det er noget man normalt ikke kan i Linq fordi hvis du laver en custom
property, og vil bruge den i en select statement, saa kan Linq ikke
finde ud af at lave den til en expression som kan omsaettes til SQL.

Men jeg har fundet en maade at goere det paa alligevel! Der er vist et
par andre gutter paa nettet der ogsaa har gjort det, men jeg synes
alligevel det var meget sjovt at lave min egen implementering.

Her er et simpelt eksempel. Lad os sige du har en entity class (fx en
klasse som er autogenereret af SQLMetal), vi kan jo kalde den Project.
Den har bla. to properties der hedder Income og Expenses. Lad os sige du
tit laver queries op mod den klasse hvor du gerne vil have Overskuddet
(revenue). Revenue er defineret som Income minus Expenses. Det var nu
oplagt at tilfoeje en ekstra property til Project klassen, saaledes:

public partial class Project
{
  public double Revenue
  {
    get { return Income - Expenses; }
  }
}

Denne property kan godt bruges til fx at populere felterne i en gridview
med, EFTER du har eksekveret din query, men du kan IKKE bruge den
direkte i queryen. Fx kan du ikke skrive:

var ds = from p in myDataContext.projects where p.Revenue > 0 select p;

Det vil komme ud med en fejlmeddelelse om at propertyen Revenue ikke har
nogen SQL-implementation.

Til redning kommer min nye extension method kaldet DynamicWhere. Hvis du
skifter Where ud med DynamicWhere, og skriver din Revenue property en
lille smule op, kan det lade sig goere.

Tricket er, at du skal lade Revenue levere en Expression<Func<>> tilbage
i stedet for et resultat. Men for at queryen skal kunne acceptere
at du skriver fx p.Revenue > xxx saa skal Revenue jo vaere en property
der leverer en double. I stedet laver du saa en statisk skygge-funktion
med et andet navn som leverer en Expression tilbage. Den funktion
associerer du saa med din Revenue funktion via en attribute. Saadan her:

[DynamicProperty(ExpressionPropertyName = "RevenueExpr")]
public double Revenue
{
  get { return RevenueExpr.Compile().Invoke(this); }
}

public static Expression<Func<Project, double>> RevenueExpr
{
  get { return (p => p.Income - p.Expenses); }
}

Jeg har ladet Revenue genbruge den associerede funktion saaledes at man
ikke bliver noed til at skrive p.Income - p.Expenses to gange.

Klik her for at downloade DynamicWhere som DLL projekt.

[C# Talk] : A smarter OrderBy<> and OrderByDescendnig<>

Sunday, November 29th, 2009

Hvordan undgår man at blive nød til at kalde skiftevis OrderBy<> og OrderByDescendnig<> når man laver en custom sorting-algoritme i sit business lag i en Linq-baseret applikation? Man laver da naturligvis en extension method!

public static class ExtensionMethods
{
  public static IOrderedQueryable<TSource>
  OrderByDirection<TSource,TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, SortDirection sortDirection)
  {
    return sortDirection == SortDirection.Ascending ?
      source.OrderBy(keySelector) :
      source.OrderByDescending(keySelector);
  }
}

[C# Talk] : LALR(1) parser in C#

Tuesday, November 17th, 2009

Always being interested in parsers, I decided to try my luck on writing an LALR(1) parser in C#. Traditionally these parsers (Yacc, Bison) have been written so that you must run the scanner/lexer first, then include the output into your project as separate files.

I decided it was smarter if everything was assembled into one Parser class, which you could then instantiate in your program. I wanted to be able to configure it via a grammar also based on objects, build it, and then run the parser every time I wanted to parse a text string.

This is similar to the way the Reges class in C# works. You compile your regex first by instantiating a Regex class and give it the regex pattern, thereafter you can use it to match text strings multiple times.

Read more here…

[[[ Copyright (C) Thor Asmund 1998-2008 ]]]