Select 多列错误 entity framework(无法创建类型的空常量值)

Select many columns error entity framework (Unable to create a null constant value of type)

我不希望返回所有列,所以我尝试 select 来自 EMPLOYEES 的一些列,当 运行 以下代码时出现错误:

    var query = db.EMPLOYEES.AsQueryable();
query = ApplyFilter(query, filter);

var result = query.Select(x => new EMPLOYEE_DTO()
{
     PHONE_NO = x.PHONE_NO,
     EMAIL = x.EMAIL,
     EMP_NO = x.EMP_NO
}).ToList();

private IQueryable<EMPLOYEE> ApplyFilter(IQueryable<EMPLOYEE> query, EmployeesFilter filter)
{
   if (!string.IsNullOrEmpty(filter.EMAIL))
       query = query.Where(u => u.EMAIL.ToLower().Contains(filter.EMAIL.ToLower()));
    return query;
}

错误是:{"Unable to create a null constant value of type 'System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. Only entity types, enumeration types or primitive types are supported in this context."}

我看到一个 post 说使用 DTO 对象 (EMPLOYEE_DTO) 可以解决问题,但问题仍然存在。

请指教

关于您的 class,您并没有告诉我们很多。我假设 filter 是您本地进程中的一个 EmployeesFilter 对象; db 是一个 DbContext 类型的对象; db.EmployeesDbSet<Employee> 的对象。

filterEmployee都有一个字符串属性Email

每个 DbSet<Employee> 实施 IQueryable<Employee>。那你为什么打电话给 AsQueryable?

你的filter是局部变量。在这种情况下,只有 filter.Email 是重要的。如果此 属性 的值等于 null,则您需要所有 Employees,否则您需要 Employees 的子集,即只有那些 Employees 具有 Email 值等于过滤器中的 Email 值,忽略大小写。

现在忽略大小写总是很危险的。毕竟,不是每个人的名字都只有字母 A-Z 和 a-z。最好描述你想要什么情况下的无知:序数?当前文化?不变文化?

您似乎想要以下内容:

var query = String.IsNullOrEmpty(filter.Email) ?
    db.Employees :
    db.Employees            
      .Where(employee => String.Equals(employee.Email, filter.Email, 
           StringComparison.InvariantCultureIgnoreCase);

我不确定将其更改为 ApplyFilter 之类的额外函数是否会提高可读性,但如果您确实需要,请将其编写为 IQueryable<Employee>:

的扩展函数
static IQueryable<Employee> ApplyFilter(this IQueryable<Employee> employees, 
       EmployeeFilter filter)
{
    return String.IsNullOrEmpty(filter.Email) ? 
           employees :
           employees.Where(employee => String.Equals(employee.Email, filter.Email, 
               StringComparison.InvariantCultureIgnoreCase);
}

任何查询的用法:

IQueryable<Employee> someEmployees = ...
IQueryable<Employee> filteredEmployees = someEmployees.Filter(myFilter);

我故意没有使用 var,所以你可以看到类型发生了什么。

TODO:通过添加 ToList() 检查此代码是否正确,以查看是否可以获取 Employees。但是你当然已经这样做了,不是吗?

现在是第二部分。因此,您有一个 returns 和 IQueryable<Employee> 的查询,并且您希望将每个 Employee 投影到 EmployeeDto。如果您想在查询中执行此操作,则必须确保您的 EmployeeDto 是一个 POCO:具有默认构造函数且仅获取/设置属性的 class。

如果是这种情况,您应该能够执行投影:

var result = query.Select(employee => new EMPLOYEE_DTO()
{
     PHONE_NO = employee.PHONE_NO,
     EMAIL = employee.EMAIL,
     EMP_NO = employee.EMP_NO,
})
.ToList();