簡體   English   中英

使用 LINQ 和 Lambda 加入/在哪里

[英]Join/Where with LINQ and Lambda

我在使用 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 的新手,所以我不確定這個查詢是否正確。

我發現如果您熟悉 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

你可以有兩種方法。 使用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 時,還通過由 '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

可以對同一類型或許多不同類型的一組DataLoadOptions進行多次LoadWith調用。 但是,如果您經常這樣做,您可能只想考慮緩存。

Daniel 對語法關系有很好的解釋,但我為我的團隊整理了這份文檔,以便讓他們更容易理解。 希望這有助於某人在此處輸入圖片說明

您的鍵選擇器不正確。 他們應該獲取有問題的表類型的對象並返回要在連接中使用的鍵。 我想你的意思是:

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

您可以在之后應用 where 子句,而不是作為鍵選擇器的一部分。

發帖是因為當我開始 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;}
}

我做過這樣的事情;

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);

它可能是這樣的

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};

這個 linq 查詢應該適合你。 它將獲得所有具有 post 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 等於 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 };

LINQ 連接的查詢語法

var productOrderQuery = from product in Product.Setup()//outer sequence
                        join order in OrderDetails.Setup()//inner sequence
                        on product.Id equals order.ProductId //key selector
                        select new//result selector
                        {
                            OrderId = order.Id,
                            ProductId = product.Id,
                            PurchaseDate = order.PurchaseDate,
                            ProductName = product.Name,
                            ProductPrice = product.Price
                        };

LINQ 連接的方法語法

var productOrderMethod = Product.Setup().//outer sequence
    Join(OrderDetails.Setup(), //inner sequence
    product => product.Id//key selector
    ,order=> order.ProductId //key selector
    ,(product,order)=> //projection result
        new
        {
            OrderId = order.Id,
            ProductId = product.Id,
            PurchaseDate = order.PurchaseDate,
            ProductName = product.Name,
            ProductPrice = product.Price
        }
    );

Product.cs 供參考

class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    public decimal Price { get; set; }
    public static IEnumerable<Product> Setup()
    {
        return new List<Product>()
        {
            new Product(){Id=1, Name="Bike", Price=30.33M },
            new Product(){Id=2, Name="Car", Price=50.33M },
            new Product(){Id=3, Name="Bus", Price=60.33M }
        };
    }
}

OrderDetails.cs 類供參考

class OrderDetails
{
    public int Id { get; set; }
    public virtual int ProductId { get; set; }

    public DateTime PurchaseDate { get; set; }
    public static IEnumerable<OrderDetails> Setup()
    {
        return new List<OrderDetails>()
        {
            new OrderDetails(){Id=1, ProductId=1, PurchaseDate= DateTime.Now },
            new OrderDetails(){Id=2, ProductId=1, PurchaseDate=DateTime.Now.AddDays(-1) },
            new OrderDetails(){Id=3, ProductId=2, PurchaseDate=DateTime.Now.AddDays(-2) }
        };
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM