'FromSql' 操作的结果中不存在所需的列 'xxxID' - .Net Core EF

The required column 'xxxID' was not present in the results of a 'FromSql' operation - .Net Core EF

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

型号:

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

和数据库table为:

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: The required column 'EmpID' was not present in the results of a 'FromSql' operation.

ASP.NET 核心 EF 生成查询:

DELETE FROM [dbo].[Employee]

fail: Microsoft.EntityFramework.Query[10100] .... stack trace with above error.

已经调查过:

所以不确定为什么会抛出上述错误。因为数据库有正确的 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;

问题

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