2014-10-02 57 views
3

這裏是我的代碼:的LINQ表達式包含與不同的上下文相關的查詢引用

var myStrings = (from x in db1.MyStrings.Where(x => homeStrings.Contains(x.Content)) 
        join y in db2.MyStaticStringTranslations on x.Id equals y.id 
        select new MyStringModel() 
        { 
         Id = x.Id, 
         Original = x.Content, 
         Translation = y.translation 
        }).ToList(); 

我也得到指定的LINQ表達式包含對與不同上下文關聯的查詢引用錯誤。我知道問題是我試圖從db1和db2訪問表,但我該如何解決這個問題?

+2

單個表是否足夠小以適應內存?兩張桌子中的哪一張比另一張大得多? – dasblinkenlight 2014-10-02 19:57:11

+2

Linq將優化查詢發送到數據庫,因此如果有兩個上下文,就不可能將優化查詢發送到數據庫。正如@dasblinkenlight所說,如果表很小,請將數據帶到內存中,並在IEnumerable上執行連接,而不是Iqueryable。 – 2014-10-02 20:02:02

+0

@dasblinkenlight MyStrings是一個小表。 – 2014-10-02 20:22:43

回答

5

MyStrings是小表

裝載在存儲器過濾MyStrings,然後用MyStaticStringTranslations使用LINQ加入:

// Read the small table into memory, and make a dictionary from it. 
// The last step will use this dictionary for joining. 
var byId = db1.MyStrings 
    .Where(x => homeStrings.Contains(x.Content)) 
    .ToDictionary(s => s.Id); 
// Extract the keys. We will need them to filter the big table 
var ids = byId.Keys.ToList(); 
// Bring in only the relevant records 
var myStrings = db2.MyStaticStringTranslations 
    .Where(y => ids.Contains(y.id)) 
    .AsEnumerable() // Make sure the joining is done in memory 
    .Select(y => new { 
     Id = y.id 
     // Use y.id to look up the content from the dictionary 
    , Original = byId[y.id].Content 
    , Translation = y.translation 
    }); 
+0

很好的答案,我沒有考慮MyStaticStringTranslations的大小。我很好奇你爲什麼要做ids = byId.Keys.ToList()。你不能只寫.Where(y => byId.Contains(y.id))嗎? – 2014-10-02 22:31:06

+1

@JaredMoore是的,你絕對可以使用'by.Id.Keys.Contains(y.id)'。我爲它添加了一個單獨的行,因爲我想要評論的訂單項。 – dasblinkenlight 2014-10-03 00:42:07

+0

夠公平的。我會避免將它複製到一個單獨的列表中,因爲(1)它浪費內存,並且(2)Dictionary.Contains(),它是O(1)最好的情況和O(n)最差的情況,理論上應該比List更好。包含()總是O(n)。不是說,如果MyStrings是一個小桌子,它會產生巨大的差異。 :) – 2014-10-03 02:50:54

1

你說得對,db1和db2不能在同一個Linq表達式中使用。 x和y必須在此過程中加入,而不是由Linq提供者加入。試試這個:

var x = db1.MyStrings.Where(xx => homeStrings.Contains(xx.Content)).ToEnumerable(); 

var y = db2.MyStaticStringTranslations.ToEnumerable(); 

var myStrings = (from a in x 
       join b in y on x.Id equals y.id 
        select new MyStringModel() 
        { 
         Id = x.Id, 
         Original = x.Content, 
         Translation = y.translation 
        }).ToList(); 

參考這個答案詳細信息:The specified LINQ expression contains references to queries that are associated with different contexts

dasblinkenlight的回答有比這更好的總體方法。在這個答案中,我試圖儘量減少對原始代碼的差異。

0

我也面臨同樣的問題: 「指定的LINQ表達包含對與不同上下文關聯的查詢的引用。「 這是因爲它無法一次連接到兩個上下文,所以我找到如下的解決方案。 在這裏,在這個例子中,我想用所有者名稱列出的抽獎卡,但其所有者名稱表是在另一個Database.So我做了兩個方面DB1Context和DB2Context.and寫的代碼如下:

var query = from lc in db1.LotteryCardMaster 
      from om in db2.OwnerMaster 
      where lc.IsActive == 1 
      select new 
         { 
          lc.CashCardID, 
          lc.CashCardNO, 
          om.PersonnelName, 
          lc.Status 

         }; 

AB.LottryList = new List<LotteryCardMaster>(); 
      foreach (var result in query) 
      { 
       AB.LottryList.Add(new LotteryCardMaster() 
       { 
        CashCardID = result.CashCardID, 
        CashCardNO = result.CashCardNO, 
        PersonnelName =result.PersonnelName, 
        Status = result.Status 

       }); 
      } 

但這給了我上面的錯誤,所以我發現另一種方式來執行從不同的數據庫中的兩個表加入,這種方式如下。

var query = from lc in db1.LotteryCardMaster 
      where lc.IsActive == 1 
      select new 
         { 
          lc.CashCardID, 
          lc.CashCardNO, 
          om.PersonnelName, 
          lc.Status 

         }; 

AB.LottryList = new List<LotteryCardMaster>(); 
      foreach (var result in query) 
      { 
       AB.LottryList.Add(new LotteryCardMaster() 
       { 
        CashCardID = result.CashCardID, 
        CashCardNO = result.CashCardNO, 
        PersonnelName =db2.OwnerMaster.FirstOrDefault(x=>x.OwnerID== result.OwnerID).OwnerName, 
        Status = result.Status 

       }); 
      } 
相關問題