I would like to submit this idea to the NHibernate community:
LINQ (Language INtegrated Query) is a feature that will be available in the next version of C# and VB (to be released in 2007). Basically it allows the programmer to write static typed, intellisense enabled, compiler checked queries in C# or VB.
Code:
var expr = from s in names
where s.Length == 5
orderby s
select s.ToUpper();
Info about LINQ:
The homepage:
http://msdn.microsoft.com/netframework/future/linq/The forum:
http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=123&SiteID=1Internally the queries are represented as an expression tree, used by Microsoft to create, for example DLINQ (Database LINQ), an ORM that translates the expression tree into SQL code. I've evaluated the Community Technical Preview of LINQ and DLINQ and found that:
1. DLINQ is (like all Microsoft products) focused on mapping or generating (poorly designed) classes to an existing database (database oriented), and not mapping a database to a good fine grained domain model (like NHibernate does). This I consider is the main problem with DLINQ.
- DLINQ does not (yet?) support all inheritance mappings. The forum says that the next preview will have support for "one table per class hierarchy".
- DLINQ still misses many other things already in Nhibernate that make it the best ORM for rich object oriented domain models available (in .NET).
SO:
We could start a sourceforge project called "NHiberLINQ", using LINQ expression trees to generate HQL.
Expected benefits:
- type safe queries with intellisense!
- all the power of NHibernate
- If you need to further process a collection of objects already fetched from the database, we could use LINQ to filter, sort, page or project the collection.
- In collections inside classes: if collection is initialized it could use in memory LINQ query functions to execute code in memory and avoid writing common code, if not initialized NHiberLINQ would create the HQL and use internally Session.CreateFilter("hql expression") to execute the query)
for example consider this (sorry C# guys):
Code:
Class MegaProject
...
private _projects as EntitySet(of Project) ' Using Ayende's generics
...
Function GetProjectsWithBudgetBetween(hi as decimal, lo as decimal) as ICollection(of Project)
Dim innerSet As ISet = ReflectionHelper.GetInnerSet(_projects)
If Not NHibernateUtil.IsInitialized(innerSet) Then
' Do it from database
Dim query As IQuery = NHibernateHelper.GetCurrentSession. _
CreateFilter(innerSet, "where this.Budget between :lo and :hi order by this.Budget"). _
SetDecimal("lo", lo). _
SetDecimal("hi", hi)
Return Algorithms.TypedAs(Of Project)(query.List())
Else
' Do it in memory for speed (boilerplate code I write all the time)
Dim result As New List(Of Project)
For Each aProject As Project In _projects
If aProject.Budget >= lo And aProject.Budget <= hi Then
result.Add(aProject)
End If
Next
Return result
End If
End Function
would turn into not writing the code until needed by the client:
Code:
VB 9.0:
dim result = Select p _
From myMegaProject.Projects As p _
Where p.Budget >= 20000 and p.Budget <= 40000
C# 3.0:
var result = From p In myMegaProject.Projects
Where p.Budget >= 20000 and p.Budget <= 40000
Select p;
First steps:
- Create the sourceforge project
- Download the latest LINQ CPT
- Dissasembly the DLINQ code with Reflector to see how it works, as I've seen its allot like how the NHibernate ICriteria API works.