加入/ LINQ和Lambda的位置

Dav*_*vid 420 c# linq lambda join

我在使用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 });
Run Code Online (Sandbox Code Playgroud)

我是新手使用LINQ,所以我不确定这个查询是否正确.

Dan*_*fer 966

我发现,如果您熟悉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 };
Run Code Online (Sandbox Code Playgroud)

如果你真的坚持使用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
Run Code Online (Sandbox Code Playgroud)

  • @Emanuele Greco,关于你的编辑,"ID字段上的等同是在JOIN条件下设置的;你不需要使用WHERE子句!":WHERE子句不测试ID字段之间的相等性,它测试帖子ID之间的相等性列和在查询外声明的id参数. (8认同)
  • 令人敬畏的`lambda`和引用易于使用和理解 (7认同)

Dam*_*ell 74

你可以用两种方式.使用LINQPad(如果您是LINQ的新手,这是非常宝贵的)和虚拟数据库,我构建了以下查询:

Posts.Join(
    Post_metas,
    post => post.Post_id,
    meta => meta.Post_id,
    (post, meta) => new { Post = post, Meta = meta }
)
Run Code Online (Sandbox Code Playgroud)

要么

from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,我认为LINQ语法更清晰(我在两者之间进行了更改,具体取决于最容易阅读的内容).

我想指出的是,如果你的数据库中有适当的外键(post和post_meta之间),那么你可能不需要显式连接,除非你试图加载大量的记录.您的示例似乎表明您正在尝试加载单个帖子及其元数据.假设每个帖子都有很多post_meta记录,那么您可以执行以下操作:

var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();
Run Code Online (Sandbox Code Playgroud)

如果你想避免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
Run Code Online (Sandbox Code Playgroud)

可以对同一类型或许多不同类型LoadWith的单个集合进行多次调用DataLoadOptions.如果你这么做,你可能只想考虑缓存.


Tal*_*h27 37

Daniel对语法关系有一个很好的解释,但我把这个文档放在我的团队中,以便让他们更容易理解.希望这有助于某人在此输入图像描述

  • g =&gt; g不应该真正读为g =&gt; g.id (3认同)
  • 我并没有试图将此作为对OP发布的实际linq的引用发布,它更像是如何将SQL移动到Linq格式的参考,因此我的输入与原始问题略有不同.如果我为gStatus值创建了一个类,我会在其上放置一个id属性,然后是的,它会加入g => g.id我使用了一个值列表来尽量保持代码的简单. (3认同)

Mar*_*ers 34

您的密钥选择器不正确.他们应该采用相关表格类型的对象,并返回要在连接中使用的密钥.我想你的意思是:

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

您可以在之后应用where子句,而不是作为键选择器的一部分.


Ama*_*har 8

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
                        };
Run Code Online (Sandbox Code Playgroud)

LINQ Join 的方法语法

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
        }
    );
Run Code Online (Sandbox Code Playgroud)

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 }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)


pep*_*omb 7

它可能是这样的

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};
Run Code Online (Sandbox Code Playgroud)


And*_*y V 7

发布是因为当我开始LINQ + EntityFramework时,我盯着这些例子一天.

如果您正在使用EntityFramework,并且您MetaPost模型对象上设置了一个名为的导航属性,那么这很容易.如果您正在使用实体并且没有该导航属性,您还在等什么?

database
  .Posts
  .Where(post => post.ID == id)
  .Select(post => new { post, post.Meta });
Run Code Online (Sandbox Code Playgroud)

如果你先做代码,你就这样设置了属性:

class Post {
  [Key]
  public int ID {get; set}
  public int MetaID { get; set; }
  public virtual Meta Meta {get; set;}
}
Run Code Online (Sandbox Code Playgroud)


Aha*_*hak 6

这个 linq 查询应该适合你。它将获取所有具有帖子元的帖子。

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 });
Run Code Online (Sandbox Code Playgroud)

等效 SQL 查询

Select * FROM Posts P
INNER JOIN Post_Metas pm ON pm.postId=p.postId
Run Code Online (Sandbox Code Playgroud)

  • 这与 7 年后接受的答案相同 -1 (5认同)

Mah*_*hib 5

我做过这样的事情;

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);
Run Code Online (Sandbox Code Playgroud)