2011-07-20 90 views
24

我有一個查詢在下面,但我想執行一個Include()來提前加載屬性。操作有一個導航屬性,用戶(Action.User)LINQ表達式語法如何與Include()進行預先加載

1)我的基本查詢:

from a in Actions 
join u in Users on a.UserId equals u.UserId 
select a 

2)第一次嘗試:

from a in Actions.Include("User") 
join u in Users on a.UserId equals u.UserId 
select a 

但Action.User是人口。

3)儘量渴望負荷「用戶」進入導航屬性的動作查詢外:

(from a in Actions 
join u in Users on a.UserId equals u.UserId  
select a).Include("User") 

在LINQPad試圖包含的我得到一個錯誤:

「System.Linq.IQueryable」沒有包含'Include'的定義並且沒有擴展方法'Include'接受類型'System.Linq.IQueryable'的第一個參數可以被找到(按F4添加使用指令或程序集引用)

我認爲這是因爲LINQ不支持Include() 。

所以我嘗試在VS;查詢2運行,但返回未填充的用戶屬性。 查詢3擴展方法似乎並不存在,儘管它沒有查詢就存在於Action本身。

+0

Action-Model的屬性名爲「User」?你有DbContext嗎? – dknaack

回答

50

我想通了,您的建議,還是要謝謝你。 解決的辦法是要做到這一點(在我的問題第2次嘗試):

var qry = (from a in Actions 
join u in Users on a.UserId equals u.UserId  
select a).Include("User") 

原因智能感知沒有表現出包括之後的查詢是因爲我需要以下使用:

using System.Data.Entity; 

一切工作罰款這樣做。

+0

超級有用,謝謝! –

+2

連接將自動發生,假設您的實體在上下文中正確映射。你可以通過一個簡單的查詢來實現同樣的效果:'var qry = from Actions.Include(「User」)select a'如果你加入的實體沒有被顯式映射爲Navigation屬性(即:Action沒有User屬性,或者是由於某種原因未被映射爲導航屬性),那麼你需要加入,刪除包含,然後你可以使用'select new {Action = a,User = u}'讓EF返回加入數據。 (後者通常被稱爲投影) – JoeBrockhaus

0

我用這個LoadWith選項

var dataOptions = new System.Data.Linq.DataLoadOptions(); 
dataOptions.LoadWith<Action>(ac => as.User); 
ctx.LoadOptions = dataOptions; 

完蛋了。 ctx是你的DataContext。這對我的作品:-)

+0

這個例子使用LINQ to SQL,而問題是關於實體框架。 –

+0

你是對的,我錯過了EF標籤: -/ – Mariusz

14

如果你想要的是一個查詢,將返回所有Action實體的相關User實體實際上是通過Action.UserIdforeign key property存在,這將做到這一點:

var results = context.Actions 
    .Include("User") 
    .Where(action => 
     context.Users.Any(user => 
      user.UserId == action.UserId)); 

但是你不必爲了過濾而使用外鍵屬性,因爲您也有navigation properties。所以,你的查詢可以通過在這個例子中篩選對Action.User導航屬性,而不是像被簡化:

var results = context.Actions 
    .Include("User") 
    .Where(action => action.User != null); 

如果模型指出Action.User屬性不能爲空(即在Action.UserId外鍵是不是在數據庫可爲空),你想要的東西實際上是所有Action實體及其關聯Users,那麼查詢變得更簡單

var results = context.Actions.Include("User"); 
+0

嗨,你的例子都顯示了鏈式方法,我的查詢是在表達式語法中,如上所示(使用from/select)。你能告訴我如何做到這一點? – jaffa

2

做在你贏了」你貼出的問題中提到的基本查詢T爲能夠看到用戶的屬性,除非你返回一個匿名類型如下:

from a in Actions 
join u in Users on a.UserId equals u.UserId 
select new 
{ 
    actionUserId = a.UserId 
    . 
    . 
    . 
    userProperty1 = u.UserId 
}; 

但是使用包括關於ObjectContext的方法,你可以使用以下命令:

確保您已使用以下行惰性加載關:

entities.ContextOptions.LazyLoadingEnabled = false; 

然後繼續通過

var bar = entities.Actions.Include("User"); 
var foo = (from a in bar 
      select a); 
+0

從我的理解來看,'Include(「User」)'是爲了觸發急切的加載,所以通過'LazyLoadingEnabled = false'關閉延遲加載最多是多餘的,但最終會誤導。我認爲如果你想交換你的'foo'和'bar',那麼Include就會在EF查詢上工作,並且迫切地加載額外的表。 – Zorgarath

6

更好,重構友好代碼(EF6)

using System.Data.Entity; 
[...] 
var x = (from cart in context.ShoppingCarts 
where table.id == 123 
select cart).Include(t => t.CartItems); 

var x = from cart in context.ShoppingCarts.Include(nameof(ShoppingCart.CartItems)) 
where table.id == 123 
select cart; 

更新2017年3月31日

您還可以使用包括lambda語法對於任一方法:

var x = from cart in context.ShoppingCarts.Include(p => p.ShoppingCart.CartItems)) 
where table.id == 123 
select cart; 
+1

感謝您使用'nameof()'。我一直看到硬編碼的表名字符串。 – Zorgarath

+1

在C#6中添加的所有功能中,nameof是我用過的最多的功能之一!感謝您的反饋! – K0D4