2014-01-10 53 views
0

因此,我正在使用實體框架將具有普通SQL查詢的舊項目轉換爲ORM。所以我創建的數據庫模型是這樣的:如何與實體框架中的對象連接

Database model

所以只好我想翻譯到LINQ表達

SELECT UGLINK.USERNAME 
FROM GMLINK 
INNER JOIN UGLINK 
ON GMLINK.GROUPID = UGLINK.GROUPID 
WHERE (((GMLINK.MODULEID)=%ID%)) 

和我有問題,這個舊的查詢是,我可以」弄清楚如何使用對象進行連接查詢。 相反,我得走了,雖然這樣的性能(這似乎是工作):

// So this is one of the module objects that is located in a listView in the GUI 
Module m = ModuleList.selectedItem as Module; 

/* Now I want to fetch all the User objects that, 
* via a group, is connected to a certain module */ 
var query = context.gmLink 
    .Join(context.ugLink, 
      gmlink => gmlink.GroupId, 
      uglink => uglink.GroupId, 
      (gmlink, uglink) => new { gmLink = gmlink, ugLink = uglink }) 
    .Where(gmlink => gmlink.gmLink.ModuleId == m.ModuleId) 
    .Select(x => x.ugLink.User); 

所以,正如我說的這個工程,但你看我種得通過鏈接表的屬性將模塊連接.GroupId.ModuleId等等。相反,我想通過由EF創建的對象。

我想寫一個這樣的問題,但無法弄清楚如何去做,是否可能?

var query = context.User 
      .Select(u => u.ugLink 
       .Select(uglink => uglink.Group.gmLink 
        .Where(gmLink => gmLink.Module == m))); 

回答

1

這應該是工作:

var query = context.gmLink 
    .Where(gmlink => gmlink.ModuleId == m.ModuleId) 
    .SelectMany(gmlink => gmlink.Group.ugLink) 
    .Select(uglink => uglink.User); 

這是不可能的過濾器EF使用.Where(gmlink => gmlink.Module == m) gmLinks,所以這個比較需要用標識符來完成。另一種選擇是.Where(gmlink => gmlink.Module.ModuleId == m.ModuleId)

0

我沒有測試過,但這樣的事情:

var users = context.User 
    .Where(x => x.ugLink 
     .Any(y => context.gmLink 
        .Where(z => z.ModuleId == m) 
        .Select(z => z.GroupId) 
        .Contains(y.GroupId) 
     ) 
    ) 
    .ToList(); 
+0

好吧,這個例外情況是m必須用m.ModuleId代替,所以從某種意義上來說,這更好,我的嘗試,但它仍然加入'.ModuleId'和'.GroupId'即。原型而不是對象(但也許這是唯一的出路? – Markus

1

如果已經啓用了延遲加載,你不需要申請加入特殊符號(你可以直接訪問導航屬性) - 但是針對SQL運行的查詢效率不高(通常結果會在多個不同的select語句中返回)。

我的首選是禁用上下文的延遲加載,並使用.Include()表示法手動將表連接在一起,從而產生通常更高效的查詢。 .include()用於在Entity Framework中顯式連接實體。

Join()具有誤導性,並且不適合在EF中連接表。

因此,複製此聲明:

SELECT UGLINK.USERNAME 
FROM GMLINK 
INNER JOIN UGLINK 
ON GMLINK.GROUPID = UGLINK.GROUPID 
WHERE (((GMLINK.MODULEID)=%ID%)) 

您可以使用以下:

var query = context.gmLink 
    .Include(x => x.Group.gmLink) 
    .Where(x => x.ModuleId == myIdVariable) 
    .Select(x => new { 
     UserName = x.Group.ugLink.UserName 
    }); 

假設你的導航屬性的設置是否正確。我沒有測試過,所以我不是100%的語法。

當你編寫並運行LINQ to Entity查詢對數據庫時,你應該真的運行SQL profiler,這樣你就可以理解實際生成和運行的數據庫。很多時候,EF查詢可能正常運行,但是在部署到生產系統時可能會遇到性能問題。

This whitepaper可能會幫助你。

+0

嗯,啊,好吧,這看起來非常非常整齊,但我最初的表達只獲取用戶名而不是整個用戶,我沒有注意到對不起,但我需要用戶對象... – Markus

+0

已更新爲僅輸出用戶對象,您可以使用.Select()以預測輸入允許的任何形式進行項目輸入。 – Spikeh

+1

正確對待您,抱歉 - 難以編寫定製代碼準確,當你沒有在你面前VS時:) – Spikeh