Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataContext compiled query problem with .NET 4

My project (UI layer is asp.mvc) was developed using .NET 3.5. After upgrading to .NET 4.0 I have got problem with compiled queries:

 [ArgumentException: Query was compiled for a different mapping source than the one associated with the specified DataContext.]
   System.Data.Linq.CompiledQuery.ExecuteQuery(DataContext context, Object[] args) +863348
   System.Data.Linq.CompiledQuery.Invoke(TArg0 arg0, TArg1 arg1) +110

Every time when I run my query I am passing my context

return StaticQueries.getTopFiveOrders(mContext, int howMany);


public static Func<Mycontext, int, IQueryable<Order>> getTopFiveOrders
            = CompiledQuery.Compile
                ((Mycontext mContext, int howMany) =>
                 ( some query).Distinct());

The error occurs on the second request.

like image 662
marcinn Avatar asked Oct 11 '10 07:10

marcinn


2 Answers

This is due to a change in the way compiled queries operate.

They now need to be always run using the same context.

This Microsoft connect page explains why the change was made:

The problem in this case is caused by the fact that CompiledQuery requires the same mapping source to be used for all executions. In the code example you are using to reproduce the problem, the different instances of the DataContext using a new mapping source every time, but the query fails to report this, and just silently fails. If you use the DataContext.Log property or other logging like SQL Server Profiler, you will see that the second UPDATE is not even being sent to the server.

This has been fixed in .NET Framework 4.0 so that an exception is reported that will contain a message like "Query was compiled for a different mapping source than the one associated with the specified DataContext.", and it won't just silently fail. However, the code you provided that is working is the correct way to do this, because it uses the same static mapping source for all instances of LinqTestDataContext.

Basically it was always a problem but used to fail silently, they just made the failure explicit in .NET 4.

like image 170
ChrisF Avatar answered Oct 01 '22 22:10

ChrisF


I spent a good amount of time looking at this and how the behavior has been changed in .NET 4.0. I've detailed my findings more thoroughly in my blog here:

http://www.roushtech.net/2014/01/19/statically-compiled-linq-queries-broken-in-net-4-0/

The rough of it is: Microsoft made a change to protect people from doing something dumb (reusing a compiled query between different mappings), but appear to have broken a major performance benefit (reusing a compiled query between different contexts of the SAME MAPPING, but different instances of the mapping).

Using getters, or a CompiledQuery that is a member of your class will just result in constant recompilation, and no real performance benefit.

like image 28
StrangeWill Avatar answered Oct 01 '22 20:10

StrangeWill