2010-05-04 137 views
266

我在用Linq和Lambda編寫的查詢時遇到問題。到目前爲止,我得到了很多的錯誤,這裏是我的代碼:C#加入/ Linq和Lambda在哪裏

int id = 1; 
var query = database.Posts.Join(database.Post_Metas, 
           post => database.Posts.Where(x => x.ID == id), 
           meta => database.Post_Metas.Where(x => x.Post_ID == id), 
           (post, meta) => new { Post = post, Meta = meta }); 

我是新來使用LINQ,所以我不知道如果此查詢是正確的。

+6

什麼是你想實現什麼? – GerManson 2010-05-04 17:55:45

+2

你想讓查詢在句子中做什麼? – hunter 2010-05-04 17:55:48

+4

你的關鍵選擇器*方式太複雜。如果你想通過id來選擇,只需要x => x.ID即可。 – 2010-05-04 18:00:50

回答

616

我覺得,如果你熟悉的SQL語法,使用LINQ查詢語法更清晰,更自然,更容易發現錯誤:

var id = 1; 
var query = 
    from post in database.Posts 
    join meta in database.Post_Metas on post.ID equals meta.Post_ID 
    where post.ID == id 
    select new { Post = post, Meta = meta }; 

如果你真的憋屈儘管使用lambdas,但是你的語法有點不合適。下面是相同的查詢,使用LINQ擴展方法:

var id = 1; 
var query = database.Posts // your starting point - table in the "from" statement 
    .Join(database.Post_Metas, // the source table of the inner join 
     post => post.ID,  // Select the primary key (the first part of the "on" clause in an sql "join" statement) 
     meta => meta.Post_ID, // Select the foreign key (the second part of the "on" clause) 
     (post, meta) => new { Post = post, Meta = meta }) // selection 
    .Where(postAndMeta => postAndMeta.Post.ID == id); // where statement 
+4

@Emanuele Greco,關於您的編輯,「ID字段上的平等設置爲JOIN條件;您不需要使用WHERE子句!」:WHERE子句不測試ID字段之間的相等性,它正在測試帖子ID列和在查詢外聲明的id參數。 – 2013-05-27 15:45:02

+2

一塊'lambda'真棒,並且是易於使用和理解的報價 – ppumkin 2013-07-11 09:27:22

+0

謝謝,linq查詢清楚。 – 2017-04-13 13:11:44

24

您的主要選擇是不正確的。他們應該使用有關表的類型的對象並返回用於連接的鍵。我想你的意思是這樣的:

var query = database.Posts.Join(database.Post_Metas, 
           post => post.ID, 
           meta => meta.Post_ID, 
           (post, meta) => new { Post = post, Meta = meta }); 

可以事後申請where子句,不作爲重點選擇的一部分。

48

你可以用這兩種方法。使用LINQPad(無價的,如果你是新來的LINQ)和一個虛擬的數據庫,我建立以下查詢:

Posts.Join(
    Post_metas, 
    post => post.Post_id, 
    meta => meta.Post_id, 
    (post, meta) => new { Post = post, Meta = meta } 
) 

from p in Posts 
join pm in Post_metas on p.Post_id equals pm.Post_id 
select new { Post = p, Meta = pm } 

在這種特殊情況下,我認爲LINQ語法是清潔(我根據哪一個最容易閱讀而在兩者之間切換)。

但我想指出的是,如果你的數據庫中有適當的外鍵(post和post_meta之間),那麼你可能不需要顯式連接,除非你試圖加載大量的記錄。你的例子似乎表明你正在嘗試加載一個帖子,它是元數據。假設有許多post_meta記錄每一個職位,那麼你可以做到以下幾點:

var post = Posts.Single(p => p.ID == 1); 
var metas = post.Post_metas.ToList(); 

如果你想避免N + 1點的問題,那麼你就可以明確地告訴LINQ to SQL來加載所有的相關的(儘管當你更熟悉L2S時,這可能是一個高級話題)。下面的例子說:「當你加載後,還加載其所有通過由‘Post_metas’屬性表示的外鍵與它相關的記錄」:

var dataLoadOptions = new DataLoadOptions(); 
dataLoadOptions.LoadWith<Post>(p => p.Post_metas); 

var dataContext = new MyDataContext(); 
dataContext.LoadOptions = dataLoadOptions; 

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically 

它有可能使在許多LoadWith電話單一DataLoadOptions爲同一類型,或許多不同類型。如果你這麼做,你可能只想考慮緩存。

+0

*** LinqPad ***和** CRM 2016 **? – Kiquenet 2016-12-07 14:40:37

2

這可能是一些像

var myvar = from a in context.MyEntity 
      join b in context.MyEntity2 on a.key equals b.key 
      select new { prop1 = a.prop1, prop2= b.prop1}; 
5

發帖,因爲當我開始LINQ +的EntityFramework,我在這些例子中,每天盯着。

如果您使用的是EntityFramework,並且您的Post模型對象設置了名爲Meta的導航屬性,那麼這很容易。如果您使用實體並且沒有該導航屬性,那麼您還在等什麼?

database 
    .Posts 
    .Where(post => post.ID == id) 
    .Select(post => new { post, post.Meta }); 

如果你第一次做的代碼,你會設置該屬性正是如此:

class Post { 
    [Key] 
    public int ID {get; set} 
    public int MetaID { get; set; } 
    public virtual Meta Meta {get; set;} 
} 
8

丹尼爾的語法關係的一個很好的解釋,但我把這個文件一起爲我的球隊以便讓他們理解起來更簡單一些。希望這可以幫助別人enter image description here

1

這個linq查詢應該爲你工作。它將獲得所有帖子後有meta。

var query = database.Posts.Join(database.Post_Metas, 
           post => post.postId, // Primary Key 
           meta => meat.postId), // Foreign Key 
           (post, meta) => new { Post = post, Meta = meta }); 

相當於SQL查詢

Select * FROM Posts P 
INNER JOIN Post_Metas pm ON pm.postId=p.postId 
1

我做了這樣的事情;

var certificationClass = _db.INDIVIDUALLICENSEs 
    .Join(_db.INDLICENSECLAsses, 
     IL => IL.LICENSE_CLASS, 
     ILC => ILC.NAME, 
     (IL, ILC) => new { INDIVIDUALLICENSE = IL, INDLICENSECLAsse = ILC }) 
    .Where(o => 
     o.INDIVIDUALLICENSE.GLOBALENTITYID == "ABC" && 
     o.INDIVIDUALLICENSE.LICENSE_TYPE == "ABC") 
    .Select(t => new 
     { 
      value = t.PSP_INDLICENSECLAsse.ID, 
      name = t.PSP_INDIVIDUALLICENSE.LICENSE_CLASS,     
     }) 
    .OrderBy(x => x.name); 
0

1等於1兩個不同的表連接

 var query = 
      from post in database.Posts 
      join meta in database.Post_Metas on 1 equals 1 
      where post.ID == id 
      select new { Post = post, Meta = meta };