【问题标题】:Updating Rows in IQueryable and Save Changes更新 IQueryable 中的行并保存更改
【发布时间】:2021-06-10 17:23:48
【问题描述】:

我正在尝试更新从数据库中检索到的 IQueryable 中的所有行。

这是执行此操作的正确方法吗?当我对此运行 Xunit 测试时,行似乎消失了。

foreach (var item in productCustomer)  // productCustomer is IQueryable
{
    item.isActiveStatus = (item.ExpirationYear < 2019);
}
_dbContext.SaveChanges();

当前使用的是 EF Core 3.1

注意:尽量避免创建全新的对象或重新映射所有内容;只想更新 20 个成员中的 1 个成员。

【问题讨论】:

  • 之前查询的逻辑是什么?
  • 那么你可能有一个全局查询过滤器。也就是说,几乎没有什么信息可以说明这一点。
  • 这种更新方法效率很低(但是,整个 EF 也是如此)。它将生成一个 SELECT 查询和许多 UPDATE 查询。虽然您可以使用单个 UPDATE 查询。

标签: c# .net entity-framework .net-core


【解决方案1】:

改变

> foreach (var item in productCustomer)

foreach (var item in productCustomer.ToList())

IQueryable 只不过是触发数据库读取的表上的选择语句。 在您将其拉入 List 或任何对您最有意义的数据类型之前,不会将任何对象存储在内存中。

【讨论】:

  • 对不起,但这些都不是真的。 foreach 语句强制执行 IQueryable 并且对象存储在 EF 的更改跟踪器中,即在内存中(前提是没有 AsNoTracking() 调用)。如果 OP 认为 ToList 修复了它,他们可能更改了其他内容。这个问题非常不清楚,“行似乎消失了”是一个非常模糊的陈述。
  • 提示:这里的适当操作是删除答案。
【解决方案2】:

您需要先获取对象,然后才能跟踪它们的更改。但是,如果您对 IQueryable 所做的只是更新成员而不涉及其他任何内容,那么只执行 UPDATE 查询会更快。

考虑:

using(var context = new SampleContext())
{
    var commandText = "UPDATE Categories SET IsActiveStatus = ExpirationYear < 2019 --WHERE <YOUR CONDITIONS>";
    //var name = new SqlParameter("@variable", "value");
    context.Database.ExecuteSqlCommand(commandText/*,<params SqlParameter[]>*/);
}

【讨论】:

  • “IQueryable 不进行更新”。不,但是 OP 的代码确实会更新,因为它们确实“首先获取对象”。
猜你喜欢
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多