【问题标题】:The required column 'xxxID' was not present in the results of a 'FromSql' operation - .Net Core EF“FromSql”操作的结果中不存在所需的列“xxxID” - .Net Core EF
【发布时间】:2021-04-08 00:39:54
【问题描述】:

我正在尝试在 .NET Core EF (3.1.9) 中找到更好且性能高效的批量删除方法。 (一次删除大约 500K 到 100 万条记录。)

型号:

public class Employee
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int EmpID { get; set; }
    public string EmpName { get; set; }
}

而数据库表为:

CREATE TABLE [dbo].[Employee]
(
    [EmpID] [int] IDENTITY(1,1) NOT NULL,
    [EmpName] [nchar] (20) NULL,

    CONSTRAINT [PK_dbo].[Employee] 
        PRIMARY KEY CLUSTERED ([EmpID] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

尝试使用通用方法 1 删除记录。

public int Delete<TEntity>(Func<TEntity, bool> predicate) where TEntity: class
{
    return DbContext.Set<TEntity>
                    .FromSqlRaw($"Delete from dbo.Employee")
                    .Where(predicate).Count();
}

并将此方法称为

Func<Employee, bool> myPredicate = x => x.EmpID > 10;
int deletedCount = myclass.Delete(myPredicate);

抛出异常:

InvalidOperationException:“FromSql”操作的结果中不存在所需的列“EmpID”。

ASP.NET Core EF 生成查询:

DELETE FROM [dbo].[Employee]

失败:Microsoft.EntityFramework.Query[10100] .... 出现上述错误的堆栈跟踪。

已经调查过了:

.NET Core Entity Framework InvalidOperationException

The required column 'CustomerId' was not present in the results of a 'FromSql' operation

The required column 'id' was not present in the results of a `FromSql` operation in EFcore

所以不知道为什么它会抛出错误。由于数据库具有正确的 PK 并且模型也具有它。也尝试了其他一些实体,它总是抛出与列名“xxxEntityColID”相同的错误。

但是,如果我使用以下代码,那么它可以工作:

public int Delete<TEntity>(string whereCondition, params object[] parameters) where TEntity: class
{
    return DbContext.Database.ExecuteSqlRaw($"Delete from dbo.Employee WHERE {whereCondition}", parameters);
}

// and calling like 
string myCondition = "EmpID > 10";
int deletedCount = myclass.Delete<Employee>(myCondition, new object[0]);

.NET Core EF 生成以下 SQL 并且可以正常工作。

DELETE FROM [dbo].[Employee] WHERE EmpID > 10;

问题

  • 为什么会出现这个“xxxEntityColID”错误?
  • 在 .NET Core EF 中进行批量删除的更好方法是什么?

【问题讨论】:

  • 仅供参考:我已经尝试过 dbContext.RemoveRange(entities),它可以工作,但是它会为每个实体生成单独的查询。所以我认为这将是性能开销。

标签: entity-framework-core-3.1


【解决方案1】:
  1. 看起来 FromSqlRaw() 与“SELECT..”查询一起使用。
  2. 对于批量删除,我评估了以下方法,它比 dbContext.RemoveRange(entities);因为 RemoveRange() 为每个实体生成单独的查询。然后每个查询都需要一些时间,因此不适合批量删除。相比之下,ExecuteSqlRaw(带有 where 条件)只生成单个查询,对于 20 万条记录几乎不需要 250 毫秒。在高端服务器上肯定会更少。
public int Delete<TEntity>(string whereCondition, params object[] parameters) where TEntity: class
{
    return DbContext.Database.ExecuteSqlRaw($"Delete from dbo.Employee WHERE {whereCondition}", parameters);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-20
    • 2020-07-02
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多