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,我們的錯誤消失了,看來最后的推測是對的。

謹以此文,權當拋磚引玉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM