ChatGPT解决这个技术问题 Extra ChatGPT

使用 LINQ 和 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 的新手,所以我不确定这个查询是否正确。

你想达到什么目的?
你想让查询在句子中做什么?
您的键选择器太复杂了。如果要按 id 选择,只需 x=>x.ID 即可。
我想从数据库中获取帖子以及该帖子的元数据。

D
Daniel Schaffer

我发现如果你熟悉 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 };

但是,如果您真的坚持使用 lambda,那么您的语法就有点偏离了。这是使用 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

@Emanuele Greco,关于您的编辑,“ID 字段的相等性在 JOIN 条件下设置;您不需要使用 WHERE 子句!”:WHERE 子句不是测试 ID 字段之间的相等性,而是测试帖子 ID 之间的相等性列和在查询之外声明的 id 参数。
lambda 的精彩片段,引文易于使用和理解
有时对 lambda 的解释是用 lambda 编写的。解释得很好。
我一直在尝试使用 .includes,但它只能让我到目前为止。 “来自数据库中的帖子。帖子”方法是我必须记住的。我还有一个 DapperDb 注入到我的控制器中以进行复杂的查询,但对于简单的连接,我将使用 database.Posts 中的 from post 示例。它真的很方便。如果我遭受任何性能损失,那么将查询转换为 Dapper
meta.Post_ID 不会是限制连接行数的内部键,这是否意味着如果目标是查找带有元数据的某个帖子(如果存在),即使该帖子在 Posts 表中,如果它没有元数据,它不会是结果集的一部分吗?
D
Damian Powell

你可以有两种方法。使用 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

可以针对同一类型或许多不同类型对一组 DataLoadOptions 进行多次 LoadWith 调用。如果你做了很多,你可能只想考虑缓存。


LinqPad 和 CRM 2016 ?
T
Talspaugh27

https://i.stack.imgur.com/rqfoa.png


当您只是像我们在这里一样处理一个值列表时,这将不起作用。对象上没有 id 属性。
我确实发现这非常有用,但是我遇到了一个错误,需要我添加连接列。还查看@Mark Byers 发布的答案,加入列在第二个别名 meta => meta.Post_ID 中有 Post_ID 字段。在此插图的示例中,原始选择语句 JOIN gStatus g on g.idg.id 部分未在最终 Lambda 表达式中复制。
我并没有试图将其发布为对 OP 发布的回答所需的实际 linq 的参考,它更多的是关于如何将 SQL 移动到 Linq 格式的参考,因此我的输入与原始问题略有不同。如果我为 gStatus 值创建了一个类,我会在其上放置一个 id 属性,然后是的,它会与 g => g.id 结合,我使用值列表来尝试使代码尽可能简单。
@Talspaugh27 那么为什么在 SQL 查询中它会加入 g.id 上的 gStatus 呢?这是一个错误还是故意的?
@Drammy 在 sql 表中的每一列都必须有一个名称,所以由于这是一个严格用于保存这些 id 的 1 列表,我只使用了一个名为 id 的列,即 List;没有那个问题。如果我将它设置为 public class IdHolder{ int id } 然后在 gStatus List<IdHolder> gStatus = new List<IdHolder>(); gStatus.add(new IdHolder(){id = 7}); gStatus.add(new IdHolder(){id = 8}); 中使用该对象,那么它会将 Linq 更改为 t =>t.value.TaskStatusId, g=>g.id 这种更改有意义吗?
M
Mark Byers

您的键选择器不正确。他们应该获取相关表类型的对象并返回要在连接中使用的键。我想你的意思是:

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

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


A
Andy V

发帖是因为当我开始 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;}
}

M
Mahib

我做过这样的事情;

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

T
Talspaugh27

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

等效的 SQL 查询

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

你关闭了第三个参数之后的括号......“Join 没有重载需要三个参数”
这与接受的答案相同,7 年后 -1
m
mxmissile

可能是这样的

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

A
Aman singh Parihar

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

}

您能否在 LINQ Join 的方法语法中提供 where 条件的答案
E
Eray Balkanli

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