编译的查询失败 - 为与指定的DataContext关联的映射源编译的查询不同

isp*_*iro 11 .net c# sql sql-server linq-to-sql

我有一个编译的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);
}
Run Code Online (Sandbox Code Playgroud)

ServiceCustomContext继承自DataContext并且只有(除了构造函数)Table包括Current上面示例中使用的名称的表.

我得到以下异常:

'查询是针对与指定的DataContext关联的映射源而编译的.

这仅在使用如上所述的编译查询时.只要我有一个简单的:

return db.Current.Count();
Run Code Online (Sandbox Code Playgroud)

Count()方法中,一切都很好.

我不明白什么是错的.我认为可能需要保留对DataContext(ServiceCustomContext)的引用,尽管这看起来很直观,但即使是微软的例子也不会这样做.我发现的唯一解释是,这里基本上是上面链接中的Microsoft示例中提到的编译查询是非常错误的.我怀疑这是真的.

Ima*_*tas 2

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;
    }
Run Code Online (Sandbox Code Playgroud)

您可以看到它的作用,它实际上仅在第一次调用时才编译查询。它还会保存对您的引用DataContext.Mapping.MappingSource,并确保您MappingSource在每次后续调用中都使用相同的引用。

默认情况下,每次创建新的 时,都会同时创建DataContext一个新的。MappingSource这是在构造函数中完成的,并且以后无法覆盖它,因为DataContext.MappingMetaModel.MappingSource属性都只有一个公共 getter。但是,有一个构造函数重载,DataContext它以 aMappingSource作为参数,(幸运的是)允许您在应用程序的整个生命周期中重用单个映射源。

不确定您的ServiceCustomContext类的确切构造函数是什么,但以下代码应该为您提供解决方案的提示,以防止错误发生:

public class ServiceCustomContext : DataContext
{
    private static readonly MappingSource mappingSource = new AttributeMappingSource();

    public ServiceCustomContext(string connection) : base(connection, mappingSource)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我假设您使用属性来声明映射,但是XmlMappingSource如果您使用 XML 文件进行数据库映射,则可以使用属性。