I'm looking at the option of using Linq To SQL for persistence.
Basic assumptions:
Today I'm using NHibernate (so 1 and 3 are set), and AR Attributes (so 4 is set). As for querying, I resort to hql (nice, yet too stringy), ICriteria (still stringy) and NHQG (cool, super cool, yet coupled with NH, while Linq is a "query everything" language)
I tried Linq for SQL (on a VS C# 2008 Express Beta2). No designer. Hand coded the entity, and have used the attributes for mapping.
First problem encountered: in order to make a column lazy, I need to change the underlying type to Link<MyOriginalType>, and then I can tell the context (using a LoadingOptions) about whether to load the lazy properties.
Couldn't yet find a way to actually lazy load that property once the instance has already been loaded.
I much better like the way NH is handling things, with a runtime-generated proxy that takes care of lazy loading (among other stuff), so I get it without hassling my entities code.
Didn't even mention First and Second Level Caches.
I guess I'd have to try and hop into NHibernate.Linq, and try to help Ayende with bringing it forward. That would mean diving into NH code, something I haven't done for quite some time now ...
I've spent some times lately with Linq To SQL and have played a bit with the Mapping namespace.
Why I do not like it very much is a matter for a different post. The matter at hand is that I want the power of Linq, and I want the power of NHibernate, and I want the easy road of ActiveRecord.
What do I mean by that? I'd like:
the needed prequisites:
So, Ayende has kick-started it, and with some help from Bobby Diaz, we have a prototype level NHibernate provider for Linq.
To make it work with ActiveRecord, all you need is to add:
using System;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
using NHibernate;
namespace NHibernate.Linq
{
public class ActiveRecordContext : NHibernateContext
{
public ActiveRecordContext() : base(null)
{
session = GetSession();
}
private ISession GetSession()
{
ISessionScope scope = SessionScope.Current;
if (scope == null)
throw new InvalidOperationException("You should be in a SessionScope()");
ISessionFactoryHolder holder = ActiveRecordMediator.GetSessionFactoryHolder();
return holder.CreateSession(typeof(ActiveRecordBase));
}
}
}
and now you can do stuff like:
using (new SessionScope())
{
ActiveRecordContext context = new ActiveRecordContext();
var q =
from c in context.Session.Linq<Category>()
select c;
foreach (Category c in q)
Console.WriteLine(c.Name);
}
Assuming Category has [ActiveRecord] mapping.
There are many methods to query your data when you're on Castle's ActiveRecord.
Thanks to Ayende, we have a new cool way of doing that, namely NHibernate Query Generator 1.5.
1. You can skip querying, fetch everything and check it in the client:
1: Blog[] blogs = Blog.FindAll();2: foreach (Blog blog in blogs)
3: {4: if (blog.Name== "Cool Blog")
5: { 6: firstPostTitleName = blog.Posts[0];7: break;
8: } 9: }The Good: Type safety - can catch a lot of errors in compile time
The Bad: One should let the DBMS handle queries. It's a total waste of resources.
The Bottom line: AVOID
2. You can use direct SQL:
1: string firstPostTitleName = (string)ActiveRecordMediator.ExecuteQuery(
2: new ScalarQuery(typeof(string), QueryLanguage.Sql, @"
3: SELECT TOP 1 Title 4: FROM Post INNER JOIN Blog ON Post.BlogId=Blog.Id5: WHERE Blog.Name= ""Cool Blog"""));
The Good: Well, it'd probably work.
The Bad: Joins? Blog.Id? hey - I thought we are using an OR/M !! plus it's not type safe,
The Bottom line: AVOID AT AL COST
3. You can use HQL:
1: string firstPostTitleName = (string)ActiveRecordMediator.ExecuteQuery(
2: new ScalarQuery(typeof(string), @"
3: select title 4: from Post p5: where p.Blog.Name = ""Cool Blog"""));
6: The Good: Working with objects, nice and readable query string.
The Bad: not type safe,
The Bottom line: Use only when 4 and 5 are not applicable.
4. You can use ICriteria:
1: string firstPostTitleName = Post.FindOne(
2: Expression.Eq("Blog.Name", "Cool Blog"));
The Good: Working with objects, less strings means less error prone.
The Bad: not type safe, and a little less readable than HQL
The Bottom line: Use only when 5 is not applicable.
5. And now you can use NQG:
1: string firstPostTitleName = Post.FindOne(
2: Where.Post.Blog.Name == "Cool Blog");
The Good: Readable, type safe.
The Bad: I do not how to invoke sql server side functions with that. And it is a little premature, so you should have solid tests. But you should have them anyway.
The Bottom line: Prefer using this method. If it fails, go to 4 or 3.
So IMHO it is a great tool, and I've went right away to test it and play a little with the source (I've even found and fixed a little bug !!).
Notice that I've tagged it under Linq, too, since it gives us a Linq-ish way to query the DB in a typesafe elegant manner. In VB.NET the query code looks even better.
Last Tuesday (06/07/2006) I gave a presentation with Oren at our company, for the company's .NET forum.
The forum is made of all the employees from all the branches of the company, who are dealing with Microsoft's development tools, at any level.
Oren talked about our in-house architecture and presented our code generating tool - Code-Agent, that incorporates our architecture to generate a full blown n-tier application from a mere SQL Server database, in just a few clicks.
Afterwards, I talked about the problems (as I see 'em) in the data querying world today, ran a quick overview of some methods and tools that help developers to solve them, and showed a bit of the way that ADO.NET vNext (ADO.NET Entities, or ADO.NET 3.0) and LINQ, come to the rescue.
After the presentations, we've talked with some of the attendees. It was delighted to meet very capable, experienced and sharp minded people, and we encouraged them to take more active part in future meeting of the forum. I hope that this forum will evolve to be a great place to share knowledge.
The presentation that accompanied my lecture can be found here (or here if your browser cannot handle it), and if you have any questions or ideas about the subjects discussed, you are more than welcome to send them to me.
If you're into automated generation of data manipulation UI, then you must check out BLinq, written by Polita Paulus of Microsoft, at http://www.asp.net/sandbox/app_blinq.aspx?tabid=62
In short, it uses DLinq to generate a DAL, and then builds simple ASP.NET pages using GridView and DetailsView Controls (developed by Polita herself), to manipulate all of the tables from the database.
In my opinion, it serves as a great prove of concept for the whole ASP.NET and Linq technologies, as the fastest RAD tool for web application development.
Just build a database, and in an eye Blinq, you have a way to manipulate it through web app.
I find it great. Aren't you?