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


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

    image

    其中的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,我们的错误消失了,看来最后的推测是对的。

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

  • 相关阅读:
    SQLServer多表连接查询
    SQLServer基本查询
    SQLServer索引
    SQLServer之数据类型
    设计模式小结
    SQL跨项目查询语法
    利用CountDownLatch和Semaphore测试案例
    JUC包下Semaphore学习笔记
    JUC包下CountDownLatch学习笔记
    JUC包下CyclicBarrier学习笔记
  • 原文地址:https://www.cnblogs.com/scy251147/p/3953726.html
Copyright © 2020-2023  润新知