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开发者_C百科:
[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.
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.
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.
I also faced the similar problem. I removed the static from the compiled queries, it works fine. Although I have yet to find out how much difference it makes on performance.
精彩评论