例如,能夠將產品表與產品類別表相聯接,獲得產品名稱和與其相對應的類別名稱性能
db.Products .Join ( db.Categories, p => p.CategoryID, c => c.CategoryID, (p, c) => new {p,c.CategoryName} ) .Where(p => p.CategoryID == 1);
這個Join對應SQL裏的inner Join, 這個很容易理解. 上面代碼裏紅色的c的類型是Categoryspa
若是我要達到SQL裏Left Join的效果, 該怎麼寫呢? 想固然的覺得,把Join改爲GroupJoin, code
db.Products .GroupJoin ( db.Categories, p => p.CategoryID, c => c.CategoryID, (p, cs) => new {p,cs.FirstOrDefault().CategoryName} ) .Where(p => p.CategoryID == 1);
上面代碼裏紅色的cs的類型是IEnumerable<Category>, 你用FirstOrDefault()只是拿到一個目錄,萬一Product Left join是有多個目錄呢?orm
因此要用.SelectMany把IEnumerable<Category> 把裏面的每個元素作投影. blog
要注意加上DefaultIfEmtyp() 纔是Left join, 假如沒有加這個,仍是Inner Join內存
db.Products .GroupJoin(db.Categories, (Product p) => p.CategoryId, (Category c) => c.CategoryId, (prod, cs) => new { prod, cs }) // cs is IEnumerable<Category> .SelectMany(prodCats => prodCats.cs.DefaultIfEmpty(), (prodCats, c) => new { prodCats.prod categoryName = c.CategoryName });
用LinQ query表達式 對應的寫法是產品
var qry = from p in db.Products join c in db.Categories on p.CategoryId equals c.CategoryId into g from pc in g.DefaultIfEmpty() select new { prodId = p.ProdId, prodCode = p.ProdCode, prodName = p.ProdName, categoryName = g.FirstOrDefault().CategoryName };
若是我只用DefaultIfEmpty(),不用GroupJoin,這樣寫能達到這個效果嗎?io
var qry = db.Products.SelectMany ( p => db.Categories.Where(c => c.CategoryId == p.CategoryId).DefaultIfEmpty(), (p, c) => new { p.ProdId, p.ProdCode, p.ProdName, c.CategoryName } );
這樣寫,若是數據量大,性能會不好. 由於它會把Products和Categories都Load到內存裏,再Match, 而不是用SQL Left Joinform
參考文章: class
https://stackoverflow.com/questions/584820/how-do-you-perform-a-left-outer-join-using-linq-extension-methods
http://linqsamples.com/linq-to-objects/join/GroupJoin-linq
https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-left-outer-joins