The specified LINQ expression contains references to queries that are associated with different contexts

今天在改写架构的时候,遇到这么个错误。当时单从字面意思,看上去错误是由join的两个不同的表来源不一致引起的。

其中的videoResult和deerpenList均来自与同一个edmx文件,所以两个表的来源不一致导致了错误的发生,这个猜想是不正确的。

正在左右为难之际,在stackoverflow上面发现了一个主题,正好解决了我的难题。这个问题的回答是这样的:

This can happen if your Context property returns a new instance every time

它的字面意思是:如果你的Context每次访问都返回一个新的实例的话,就会造成这个错误。

回想起我之前的构造:

public interface IContext<T>:IDisposable where T:class
{
	DbContext DbContext{get;}
	IDbSet DbSet{get;}
}

public class Context<T>:IContext<T> where T:class
{
	    public Context()
        {
            DbContext = new DbContext(ConfigurationManager.ConnectionStrings["GDeerGardenEntities"].ConnectionString);
            DbSet = DbContext.Set<T>();
        }

        public void Dispose()
        {
            DbContext.Dispose();
        }

        public DbContext DbContext { get; private set; }
        public IDbSet<T> DbSet { get; private set; }
}

由于每次调用,都会新建一个DbContext,所以导致错误的发生。找到原因所在,就好了,我们只需要利用autofac这个ioc容器就行,使用的时候,从容器拿就行了。

所以打开安装器,输入

install-package autofac.mvc3 -project GDeerParkWeb

然后安装完毕,注入一下:

builder.RegisterGeneric(typeof(Context<>)).As(typeof(IContext<>)).SingleInstance();

本以为这样就没问题了。但是在使用的时候,依然会出现上述的错误。

到底原因在哪里呢? 这次排查的线索都断掉了。

想了好久,最后发现可能是泛型的Context存在问题,为什么呢?

因为在取实例化的时候,按照目前的设计,实例上下文应该是这样取得:

Context<bas_video>, Context<bas_deerpen>.

这样,带来的问题就显而易见了: 这两个上下文会产生两个不同的实例!!!!!!!

为什么会产生两个不同的实例呢? 因为泛型T只是一个占位符,当实例化出来的时候,泛型的上下文当然会拿不同的实例去hold住,这样就会造成在进行join操作的时候,出现开头的错误。

如果真是这样,那么我们把去掉,不就可以了吗?

这次我们的重构如下:

 public interface IContext
    {
        IDbSet<T> DbSet<T>() where T : class;
        DbContext DbContext { get; }
    }

 public class Context:DbContext,IContext
    {
        public Context()
            : base("GDeerGardenEntities")
        {}

        public IDbSet<T> DbSet<T>() where T : class
        {
            return base.Set<T>();
        }

        public new DbContext DbContext
        {
            get;
            private set;
        }
    }

我们的容器注入如下:

 builder.RegisterType<Context>().As<IContext>().SingleInstance();

最后上阵使用,wow,我们的错误消失了,看来最后的推测是对的。

谨以此文,权当抛砖引玉。

时间: 2024-09-29 09:05:14

The specified LINQ expression contains references to queries that are associated with different contexts的相关文章

[Linq Expression]练习自己写绑定

源代码:TypeMapper.zip 背景 项目中,我们会经常用到各种赋值语句,比如把模型的属性赋值给UI,把视图模型的属性拷贝给Entity.如果模型属性太多,赋值也会变成苦力活.所以,框架编程的思维中,出现了”绑定“.绑定不仅可以简化赋值,还可以结合验证,简化绑定过程中的验证. 能实现绑定的框架很多,如AutoMapper,.Net自带的绑定机制,微软官方上还有一个利用绑定的Sample,等. 那些成熟的框架一般功能全面,考虑周全,一般推荐首选.但对于一些小项目个别情况,或许它们就会显得有些

LINQ (Language Integrated Query)

What is it? LINQ provides language-level querying capabilities and a higher-order function API to C# and VB as a way to write expressive, declarative code. Language-level query syntax: C# var linqExperts = from p in programmers where p.IsNewToLINQ se

.NET深入解析LINQ框架(一:LINQ优雅的前奏)

阅读目录: 1.LINQ简述 2.LINQ优雅前奏的音符 2.1.隐式类型 (由编辑器自动根据表达式推断出对象的最终类型) 2.2.对象初始化器 (简化了对象的创建及初始化的过程) 2.3.Lambda表达式 (对匿名方法的改进,加入了委托签名的类型推断并很好的与表达式树的结合) 2.4.扩展方法 (允许在不修改类型的内部代码的情况下为类型添加独立的行为) 2.5.匿名类型 (由对象初始化器推断得出的类型,该类型在编译后自动创建) 2.6.表达式目录树(用数据结构表示程序逻辑代码) 3.LINQ

Linq技术四:动态Linq技术 -- Linq.Expressions

前面介绍了Linq的三个方面应用:Linq to SQL, Linq to XML和Linq to Object,这篇介绍一下动态Linq的实现方式及应用场景. 命名空间: System.Linq; System.Linq.Expressions; 应用Linq的时候,我们都知道只需要Lambda表达式就行,但有些场景仅仅只使用Data Model的字段名操作是不够的或者不方便的. 场景1:假设我们需要拼接Where条件进行查询,一种方式可以拼接IQueryable的表达式.但我想像写SQL语句

LinQ to SQL 及 non-LinQ方式实现Group的Performance对比

拥有476550数据的一张数据表.使用其中的某个字段分组,然后按该字段进行排序.该需求分别使用LinQ to SQL和non-LinQ的方式实现,然后来看一下performance对比. LinQ way from p in context.Part_Part group p by p.FunctionGroup into groupedPs orderby groupedPs.Key select groupedPs LinQ way for group non-LinQ way var re

高仿Entity Framework?Linq to SQL也有春天!

开发这个框架,主要起源于有很多使用ALinq或者Linq to SQL的用户,经常向我抱怨,它们使用起来的确很爽,但是动态查询太让人纠结了.这个框架主要就是想解决客户碰到的动态查询的问题.至今为至,已经断断续续地写了一年多了,写这个框架,充满了挑战与乐趣.当然,现在更觉得,能把文档写好,更是挑战.大多数的程序员,一直对于写文档这码事,不大重视,我也是其中的一员.但是,长期地与客户打交道,让我认识到,文档是非常地重要的,而且,能把文档写好也不是件容易的事情.这次的发布,更多的精力放在了文档的编写上

C#中的LINQ

从自己的印象笔记里面整理出来,排版欠佳.见谅! 1.LINQ: 语言集成查询(Language Integrated Query) 实例: var q= from c in categories join p in products on c equals p.Category into ps select new{Category=c, Products=ps}; 2.LINQ 类型 LINQ to Objects(或称LINQ to Collection),这是LINQ 的最基本功能,针对集

.NET深入解析LINQ框架1

1.LINQ简述 2.LINQ优雅前奏的音符 2.1.隐式类型 (由编辑器自动根据表达式推断出对象的最终类型) 2.2.对象初始化器 (简化了对象的创建及初始化的过程) 2.3.Lambda表达式 (对匿名方法的改进,加入了委托签名的类型推断并很好的与表达式树的结合) 2.4.扩展方法 (允许在不修改类型的内部代码的情况下为类型添加独立的行为) 2.5.匿名类型 (由对象初始化器推断得出的类型,该类型在编译后自动创建) 2.6.表达式目录树(用数据结构表示程序逻辑代码) 3.LINQ框架的主要设

LinqProvider系列(三)如何实现自己的Linq Provider?

这篇文章将在前人的肩上,继续完成实现Linq Provider的任务. 首先,我们列出linq语法的解析过程: linq本质上就是把我们惯用的语法糖,变成了一颗表达式树,然后由不同的linq Provider根据表达式树的内容,转化为自己所需要的数据结构,进而进行真正的数据查询. 实现自己的Linq Provider不是一件很难的事情,最关键的就是实现如下接口: public TResult Execute<TResult>(System.Linq.Expressions.Expression