如何在单个 lambda 表达式中同时使用更新和加入 [关闭]

Posted

技术标签:

【中文标题】如何在单个 lambda 表达式中同时使用更新和加入 [关闭]【英文标题】:How to use both update and join in a single lambda expression [closed] 【发布时间】:2021-07-28 15:17:05 【问题描述】:

我想将我的 SQL 查询转换为 lambda 表达式。下面是 SQL 查询。我试过但未能得到预期的结果

UPDATE
    Sales
SET
    SI.ACP= SD.ACP
FROM
    Sales SI
INNER JOIN
    SaleDesc SD
ON 
    SI.GroupID= SD.GroupID;

【问题讨论】:

如果您尝试过,请告诉我们,并解释为什么它不起作用。 至少尝试编写代码。您想在 LINQ 中使用 join 或包含:docs.microsoft.com/en-us/dotnet/csharp/language-reference/… 并且可以使用 ORM 或 ADO.Net 进行更新:***.com/questions/46657813/… AFAIK 开箱即用 EF 不支持此类查询。你可以寻找一些像 bulk extensions 或 entity framework extensions 这样的库,它们可能支持这样的东西。 在原始 EF Core 中是不可能的。但是一些extensions 可能会有所帮助。我推荐linq2db.EntityFrameworkCore。请参阅文档:Update、Join 【参考方案1】:

EF Core 本身不支持批量和本机更新,一切都应通过 ChangTracker。

无论如何,您可以使用 EF Core 的可用扩展,它可以在不执行原始 SQL 的情况下做到这一点。例如linq2db.EntityFrameworkCore(免责声明:我是创作者之一)

然后你可以编写如下的 LINQ 查询:

var queryForUpdate =
   from si in ctx.Sales
   join sd in ctx.SalesDesc on si.GroupID equals sd.GroupID
   select new  si, sd 

queryForUpdate
   .Set(u => u.si.ACP, u => u.sd.ACP)
   .Update();

【讨论】:

【参考方案2】:

销售必须有 PK。 你有不同的方式来编写 LINQ。这是其中一种方法(我试图让它对你来说更具可读性。)

Sales.Dump("original");
    Sales
        .Join(
                SaleDescs,
                sales => sales.GroupID,
                desc => desc.GroupID,
                (sales, desc) => new  Sales = sales, SaleDesc = desc 
            )
            .ToList()
            .ForEach(s =>
            
                Sales.Where(sl => sl.GroupID == s.Sales.GroupID).FirstOrDefault().ACP = s.SaleDesc.ACP;
            );
            SubmitChanges();
            
    Sales.Dump("resulted");

因为我没有关于表结构的详细信息 - 我为这个例子编了一些

【讨论】:

【参考方案3】:

使用

using (var db = new MyContext())

  var p = db.Sales
        .Join(db.SaleDesc,
         left => left.GroupID,
         right => right.GroupID,
        (left, right) => new  Sales = left, ACP = right.ACP );
        
  foreach (var item in p)
  
    item.Sales.ACP = item.ACP;
    db.Sales.Attach(item.Sales);
    db.Entry(item.Sales).State = EntityState.Modified;
    db.SaveChanges();
  

using (var db = new MyContext())

    db.Sales
    .Join(db.SaleDesc,
    left => left.GroupID,
    right => right.GroupID,
    (left, right) => new  Sales = left, ACP = right.ACP ).ForEachAsync(a => a.Sales.ACP = a.ACP);
    db.SaveChanges();

【讨论】:

我希望你明白,如果有数千条记录,这将成为一场噩梦? 不,我没有考虑过,但是我认为Update()方法在底层也是一样的。 不,从我的答案更新生成与问题完全相同的 SQL,并且没有记录加载到客户端。在您的解决方案中,您加载所有内容,然后 EF 发送大量更新 当你有"var queryForUpdate = ......",即你已经加载了记录,然后执行了更新操作。 加载记录,你知道是由ToList、ToArray等发起的。这里我们只有IQueryable,它还没有执行。通过 Update 提供执行,生成适当的 UPDATE SQL。

以上是关于如何在单个 lambda 表达式中同时使用更新和加入 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Lambda 演算入门

python基础

如何使用lambda表达式/缩短onclicklisteners android studio

C#将字典的LINQ查询重构为单个lambda表达式[关闭]

在Android Studio中使用Lambda表达式

计划中的 lambda 有啥意义?