对于经编译的Linq2sql查询,我具有以下代码以对表中的行进行计数。尽管同一未编译查询运行顺利,但查询仍引发异常:
public static Func<ServiceCustomContext, int> CompiledCount
= CompiledQuery.Compile((ServiceCustomContext db) => db.Current.Count());
public static int Count()
{
using (ServiceCustomContext db = new ServiceCustomContext(Constants.NewSqlConnection))
return CompiledCount(db);
}
ServiceCustomContext
继承自DataContext
,仅(除构造方法外)Table
包括上面示例中使用的名为Current
的表。
然后出现以下异常:
'查询是针对与映射源不同的映射源进行编译的 与指定的DataContext相关联。'
仅当使用如上所述的已编译查询时,此选项才可用。只要我有一个简单的方法:
return db.Current.Count();
在Count()
方法中,一切都很好。
我不明白怎么了。我认为可能是我需要保留对DataContext(ServiceCustomContext)的引用,尽管这似乎与直觉相反,但即使the Microsoft examples也不这样做。我发现的唯一解释是here,这基本上是上面链接的Microsoft示例中提到的编译查询确实是错误的。我怀疑那是真的。
答案 0 :(得分:1)
如果在您的应用程序生存期内仅使用Count()
一次,则代码将运行良好。错误的含义恰恰是它所说的。如果您查看CompiledQuery
的代码:
private object ExecuteQuery(DataContext context, object[] args) {
if (context == null) {
throw Error.ArgumentNull("context");
}
if (this.compiled == null) {
lock (this) {
if (this.compiled == null) {
this.compiled = context.Provider.Compile(this.query);
this.mappingSource = context.Mapping.MappingSource;
}
}
}
else {
if (context.Mapping.MappingSource != this.mappingSource)
throw Error.QueryWasCompiledForDifferentMappingSource();
}
return this.compiled.Execute(context.Provider, args).ReturnValue;
}
您可以看到它的作用,它仅在第一次调用时才编译查询。它还会保存对您的DataContext.Mapping.MappingSource
的引用,并确保在以后的每次调用中都使用相同的MappingSource
。
默认情况下,每次创建新的DataContext
时,都会创建一个新的MappingSource
。这是在构造函数中完成的,以后没有办法覆盖它,因为DataContext.Mapping
和MetaModel.MappingSource
属性都只有一个公共getter。但是,DataContext
有一个构造函数重载,它以一个MappingSource
作为参数(幸运的是)允许您在应用程序的整个生命周期内重用单个映射源。
不确定ServiceCustomContext
类的确切构造函数是什么,但是以下代码应为您提供解决方案的提示,以防止发生错误:
public class ServiceCustomContext : DataContext
{
private static readonly MappingSource mappingSource = new AttributeMappingSource();
public ServiceCustomContext(string connection) : base(connection, mappingSource)
{
}
}
我假设您正在使用属性来声明映射,但是如果您使用XML文件进行数据库映射,则可以使用XmlMappingSource
。