Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,546
|
Comments: 51,161
Privacy Policy · Terms
filter by tags archive
time to read 1 min | 140 words

I have been thinking about this for a while now. Linq to NHibernate requires two to three months of full time development work in order to get to a really good usable state. The problem is that we don't have anyone working on that full time. Considering the nature of OSS, this is not surprising, but I would like to change that if I can.

I am trying to getting sponsorship from several companies that are willing to pay for the development of Linq for NHibernate. The details are very simple, if I get enough companies interested in this to dedicate enough time & resources into it, we can get it working.

If you or your company are interested in helping fund the Linq for NHibernate project, please contact me privately, and we can discuss how we go about this.

time to read 1 min | 186 words

Linq for NHibernate is not part of the 2.0 release. Linq support is planned for the 2.1 release. That said, we have been getting a lot of questions about that.

The technical reasons are not really interesting, but suffice to say that to provide good Linq support we also need to modify NHibernate slightly. Those changes happens on the trunk, which is what Linq for NHibernate is following.

However, due to all the questions that we got, I wanted to point out that Daniel Guenter has back ported the current version of Linq to NHibernate to Nhibernate 2.0 and made it available here.

Now, the disclaimer. We are not supporting this. This is an unofficial (but welcome) contribution from the community. It is likely to have bugs (in fact, we know it contains bug in the more complex Linq queries, that is why it is still under active development), and the NHibernate team response is most likely going to be, use the latest, which requires the NHibernate trunk, not the NHibernate 2.0 version.

Use at your own risk, etc.

Unreadable Linq

time to read 2 min | 354 words

Chad Myers has posted about the query objects with the repository pattern. He is trying to solve the problem of reusable pieces of queries that can be combined together. In theory, this gives you a way to compose queries in a way that hide the actual query logic. This is a good thing.

Unfortunately, the syntax leaves a lot to be desired:

_query = new TopCustomersWithLowDiscountQuery()
	.IncludePreferred();

var otherQuery = new DeliquentCustomersQuery()
	.WithPendingLitigation()
	.WithDebtOver(999);

var results = _customers
	.AsQueryable()
	.Where(_query.OrElse(otherQuery));

Note how you compose the queries, that is simply unreadable as the query complexity scale up. At the same time, we don't really have a better way of handling that since the from expression will not accept Expression<T> instances directly. What has me worried is the tendency toward over abstraction that I have seen in a few code bases. In particular, I have seen API that takes several Expression<T> objects and compose them in interesting ways. Here is an example:

var customers = repo.FindBy(
        new TopCustomersWithLowDiscountQuery()
            .IncludePreferred()
            .BelowDiscountThreshold(3)
            .WithMoreSalesThan(500)
        .AndAlso(
            new DeliquentCustomersQuery()
                .WithDebtOver(9999))
            
);

Oh, this is a really neat trick from a programming perspective, but it makes it very hard to read and understand the code. Try to add ordering and projections to this type of query. And then try to understand the code.

I don't have any great solutions for that, unfortunately, but it is a problem that is worth pointing out.

A better solution would be to integrate that with the Linq query provider to support extracting the expression tree from the query, but that is not practical as an overall solution.

time to read 1 min | 171 words

Shawn Wildermuth has bridged the gap between the two, implementing IUpdatable on top of Linq to NHibernate. This means that you can now expose your NHibernate domain model as a set of REST services.

This functionality is now included with Linq for NHibernate. Thanks Shawn!

There is a live sample here: http://www.silverlightdata.com/Simple/NHibernate.aspx

Or you can hit the URLs directly and see what kind of formatting it has:

From a technological perspective, I think this is awesome. However, there are architectural issues with exposing your model in such a fashion. Specifically, with regards to availability and scalability on the operations side, and schema versioning and adaptability on the development side.

ADO.Net Data Services are a very thin wrapper around a DB, and as such, they should be treated as such. Do not expose them where you wouldn't want to expose your DB as well.

time to read 2 min | 327 words

So for the last few hours I have been getting back into the Linq for NHibernate project, after having left it for far too long. I am beginning to think that building a Linq provider might not have been the best way to learn C# 3.0, but never mind that now.

It is with great pride that I can tell you that the following query now works:

from e in db.Employees
select new { Name = e.FirstName + " " + e.LastName, Phone = e.HomePhone }

Why is this trivial query important? Well, it is important because about a year ago I said that there is only a single feature in Linq for SQL that NHibernate doesn't have. I also promised to fix it the moment that someone would tell me what it is. No one did, so it waited until today.

The main issue had to do with the Criteria API and handling parameters, no one ever needed to do that, it seems. When they did, they generally used HQL, which did have this feature. Since I have based Linq for NHibernate on the Criteria API*, that was a problem.

Now that ReSharper works on C# 3.0, I can actually get things done there, so I sat down and implemented it. It is surprisingly difficult issue, but I threw enough code on it until it gave up (I wonder if there is a name for nested visitors... ).

At any rate, I strongly recommend that you'll take a look at the project. And bug (fixes) and other patches are welcome**.

* This decision was important for two reasons, the first was that it is generally easier to use the Criteria API programmatically, and the second was that I wanted to ensure that the Crtieria API (which I favor) was a full featured as the HQL route.

** Yes, I know that I'll regret it.

time to read 1 min | 100 words

I read this post with interest, apparently Linq for SQL is doing something odd, because I can't quite believe the results that this guy is getting. From the post:

So I dug into the call graph a bit and found out the code causing by far the most damage was the creation of the LINQ query object for every call! The actual round trip to the database paled in comparison

I can't imagine what they are doing there to cause this performance characteristics.

From my own experiments with Linq, it should definitely not produce this amount of efforts.

time to read 2 min | 363 words

Note: I am writing this post in the express hope that it would help to change the current situation.

I have been just recently informed about a significant problem with Linq for SQL. It doesn't support testing easily. You can see the bug report here, and as usual, it was closed as Won't Fix without even providing an explanation. Did I mention already that I don't like Connect's approach to it? Yes, I did.

The root problem is a fairly simple one. Linq for SQL relies on reams of generated code, which means that if I have code line this:

var customers = from c in context.Customers 
  select c;

Then I have no really easy way to mock what is going on in here. The generated code provides a concrete class without an interface, so it is very hard to mock, and naturally, System.Data.Linq.Table<T> is sealed, has internal stuff, and is utterly hostile to mocking.

You have to use mocking if you  want to use the code above without hitting the database, and this is a core part of the way a lot of people work. Linq for SQL doesn't take that into account.

The requirement for mocking aren't really that onerous, we need and interface generated for the context class, and interface for Table<T> and that the generated code will default to using interfaces by default (Best Practices, anyone?).

Having to write adapters classes is something that TDDers on the .Net platform has become very familiar with, because of the insistence of using untestable practices throughout the framework. I am fairly tired of that, and I would certainly like to be able to skip this tiring process for once.

It is shocking to me that in this day and age the Linq for SQL team can still believe utterly ignore such practices and put hurdles in the path of easy testability.

Are we back to demos vs. reality development?

To finish, this bug has been closed, so it is not possible even to vote for it. At the very least, I would like to hear an explanation, and it had better not involved "lack of resources".

time to read 1 min | 137 words

I was asked how we will approach the same Multi Query approach with Linq integration, here are some thoughts about it.

var posts = from post in data.Posts
            where post.User.Name == "Ayende"
		orderby post.PublishedDate desc;
var postsCount = posts.Count();
posts.Skip(10).Take(15);

new LinqQueryBatch()
 .Add(posts)
 .Add(postsCount)
 .Execute();//perform the query

foreach(Post p in posts)//no query
{
  Console.WriteLine(p.ToString());
}
//no query
Console.WriteLine("Overall posts by Ayende: {0}", postsCount.Single() );

The LinqQueryBatch in this case doesn't need to pass delegates to process the results, it can modify the Linq Query directly, so trying to find the result will find the one that was already loaded when we executed the multi query.

Again, this is something that I am merely thinking about, no concrete code created.

time to read 2 min | 336 words

Mike Taulty is talking about constructing queries dynamically in Linq to SQL. Sorry, but my response to that is Yuck! Here is the code that he shows:

  NorthwindDataContext ctx = new NorthwindDataContext("server=.;database=northwind");

   var query = from c in ctx.Customers
               where c.Country == "Germany"
               select c;

   if (RuntimeCriterionOneApplies()) 
   {
    query = from c in query
            where c.City == "Berlin"
            select c;
   }

   if (RuntimeCriterionTwoApplies())
   {
    query = from c in query
            where c.Orders.Sum(o => o.Freight) > 100
            select c;
   }

   foreach (Customer c in query)
   {
    Console.WriteLine(c.CustomerID);
   }

This is not constructing queries dynamically, it is choosing a query dynamically. This isn't what I talk about when I am talking about constructing a query dynamically. You can look here as what I consider a complex query that is being constructed dynamically.

Mike, how would you handle that scenario in Linq?

Update:  I really should pay more attention when I am reading the code. Sorry Mike, the code that you have will work for the scenario that I have. I don't think that the syntax is very elegant for this scenario, but it will work. I missed the "from q in query" and read is as if a new query were constructed in each if.

time to read 2 min | 218 words

Bobby Diaz is still producing some amazing stuff. The new addition is native support for SQL functions. Take a look at this code:

DateTime date = new DateTime(1960, 1, 1);

var query = ( from e in db.Employees
                   where db.Methods.Year(e.BirthDate) >= date.Year && db.Methods.Len(e.FirstName) > 4
                   select e.FirstName )
                   .Aggregate(
new StringBuilder(), (sb, name) => sb.Length > 0 ? sb.Append(", ").Append(name) : sb.Append(name));

Console.WriteLine("Birthdays after {0}:", date.ToString("yyyy"));
Console.WriteLine(query);

Check out Bobby's post for the full details. I am going to write a full overview of the current state of Linq for NHibernate soon. The situation so far is looking very nice.

FUTURE POSTS

  1. Partial writes, IO_Uring and safety - about one day from now
  2. Configuration values & Escape hatches - 5 days from now
  3. What happens when a sparse file allocation fails? - 7 days from now
  4. NTFS has an emergency stash of disk space - 9 days from now
  5. Challenge: Giving file system developer ulcer - 12 days from now

And 4 more posts are pending...

There are posts all the way to Feb 17, 2025

RECENT SERIES

  1. Challenge (77):
    20 Jan 2025 - What does this code do?
  2. Answer (13):
    22 Jan 2025 - What does this code do?
  3. Production post-mortem (2):
    17 Jan 2025 - Inspecting ourselves to death
  4. Performance discovery (2):
    10 Jan 2025 - IOPS vs. IOPS
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}