【问题标题】:Select many columns error entity framework (Unable to create a null constant value of type)选择多列错误实体框架(无法创建空常量值类型)
【发布时间】:2018-08-08 12:11:58
【问题描述】:

我不希望返回所有列,所以我试图从 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;
}

错误是:{“无法创建类型为 'System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089] 的空常量值] ]'。在此上下文中仅支持实体类型、枚举类型或原始类型。"}

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

请指教。

【问题讨论】:

  • 要了解问题是在您的查询中还是在您的选择中,如果您执行query.ToList() 会发生什么?
  • 我认为是 DTO 对象中的问题,但它也在不使用 DTO 的情况下发生。问题出在 ApplyFilter 函数“query = query.Where(u => filter.SelectedIds.Contains(u.EMP_NO));”中为 null 的过滤器值中。 SelectedIds 为空。感谢您的提示,它解决了这个问题。

标签: entity-framework linq linq-to-sql linq-to-entities


【解决方案1】:

你没有告诉我们很多关于你的课程的事情。我假设 filter 是您本地进程中的 EmployeesFilter 对象; dbDbContext 类型的对象;而db.EmployeesDbSet&lt;Employee&gt; 的对象。

filterEmployee 都有一个字符串属性 Email

每个DbSet&lt;Employee&gt; 实现IQueryable&lt;Employee&gt;。那你为什么打电话给AsQueryable

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

现在忽略大小写总是很危险的。毕竟,不是每个人的名字都只有字母 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&lt;Employee&gt; 的扩展函数:

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。当然,你已经这样做了,不是吗?

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多