6

我的项目(UI 层是 asp.mvc)是使用 .NET 3.5 开发的。升级到 .NET 4.0 后,我遇到了编译查询的问题:

 [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

每次运行查询时,我都会传递上下文

return StaticQueries.getTopFiveOrders(mContext, int howMany);


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

错误发生在第二个请求上。

4

3 回答 3

4

这是由于编译查询的操作方式发生了变化。

它们现在需要始终使用相同的上下文运行。

此 Microsoft 连接页面解释了进行更改的原因:

这种情况下的问题是由于 CompiledQuery 需要相同的映射源用于所有执行。在您用来重现问题的代码示例中,DataContext 的不同实例每次都使用新的映射源,但查询无法报告这一点,只是默默地失败。如果您使用 DataContext.Log 属性或 SQL Server Profiler 等其他日志记录,您将看到第二个 UPDATE 甚至没有发送到服务器。

这已在 .NET Framework 4.0 中得到修复,因此会报告一个异常,该异常将包含一条消息,例如“查询是为与指定 DataContext 关联的映射源不同的映射源编译的。”,它不会只是静默失败。但是,您提供的有效代码是执行此操作的正确方法,因为它对 LinqTestDataContext 的所有实例使用相同的静态映射源。

基本上它总是一个问题,但过去常常默默地失败,他们只是在 .NET 4 中明确地表明了失败。

于 2010-11-22T09:28:31.197 回答
2

我花了很多时间研究这个以及 .NET 4.0 中的行为是如何改变的。我在这里的博客中更详尽地详细介绍了我的发现:

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

粗略的是:微软做出了改变以保护人们免于做一些愚蠢的事情(在不同映射之间重用编译查询),但似乎已经破坏了主要的性能优势(在相同映射的不同上下文之间重用编译查询,但是映射的不同实例)。

使用 getter 或作为类成员的 CompiledQuery 只会导致不断重新编译,并没有真正的性能优势。

于 2014-01-19T22:41:53.967 回答
0

我也遇到了类似的问题。我从编译的查询中删除了静态,它工作正常。虽然我还没有发现它对性能有多大影响。

于 2011-11-04T10:11:05.383 回答