DataContext compiled query problem with .NET 4

2019-06-20 17:52发布

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.

3条回答
2楼-- · 2019-06-20 18:06

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.

查看更多
Root(大扎)
3楼-- · 2019-06-20 18:16

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.

查看更多
放我归山
4楼-- · 2019-06-20 18:23

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.

查看更多
登录 后发表回答