无法使用递归函数创建类型为error的常数值



我运行了一个查询,该查询按组织层次结构中的级别对员工进行分组。当用户点击一个组时,我想深入了解这些结果。

员工表看起来像:

public class Employee : IEntity
{
[Key]
[DataMember]        
public int Id { get; set; }
[Required]
[DataMember]
public string Name { get; set; }
[DataMember]
public int OrganizationEntityId { get; set; }
[DataMember]
[ForeignKey("OrganizationEntityId")]
public virtual OrganizationEntity OrganizationEntity { get; set; }
}

OrganizationEntity表如下所示:

public class OrganizationEntity : IEntity
{
[KeyAttribute()]
[DataMember]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[DataMember]
public string Name { get; set; }
[DataMember]
public int OrganizationEntityTypeId { get; set; }
[DataMember]
[ForeignKey("OrganizationEntityTypeId")]
public virtual OrganizationEntityType OrganizationEntityType { get; set; }
[DataMember]
public virtual OrganizationEntity Parent { get; set; }
public virtual ICollection<OrganizationEntity> Children { get; set; }
}

我现在用来深入这些组的代码看起来像:

private IQueryable<Employee> EmployeesByOrganizationLevel(IQueryable<Employee> employees, int orgEntityId)
{
Func<Employee, string> selector = (n => this.FindOrganization(n.OrganizationEntity, orgEntityId));
var result = employees.Where(o => o.OrganizationEntity.Name.Equals(selector));
return result;
}
private string FindOrganization(OrganizationEntity entity, int orgEntityId)
{
if (entity == null)
{
return null;
}
else if (entity.Id == orgEntityId)
{
return entity.Name;
}
else
{
return this.FindOrganization(entity.Parent, orgEntityId);
}
}

正在传入的员工是我在查询中的所有员工减去分组。对于每一条记录,我都需要遍历层次结构,找出它们是否属于传入的orgEntityId,这样其他组就不会包含在结果中。

当我在手表中打开我的结果变量时,我看到错误消息:

无法创建类型为"System"的常数值。函数"2[员工]'。在此上下文中仅支持基元类型或枚举类型。

我有非常相似的代码来为我进行分组。主要的区别是我在lambda中使用了where而不是GroupBy,所以我不确定为什么会出现这个错误。。。

如有任何帮助,我们将不胜感激。

更新(Charles要求)

这是我目前使用的groupBy代码,所以我现在所做的唯一区别是我使用的是where而不是groupBy:

private IQueryable<HeadCountRecord> GroupEmployeesByOrganizationLevel(IQueryable<Employee> employees, Enums.HeadCountGroupByGroups organizationType)
{
Func<Employee, string> selector = (n => this.FindOrganizationByType(n.OrganizationEntity, (int)organizationType));
var headCount = employees.GroupBy(selector)
.Select((o, index) => new HeadCountRecord
{
Id = index + 1,
Grouping = o.Key,
HeadCount = o.Count()
}).AsQueryable();
return headCount;
}
private string FindOrganizationByType(OrganizationEntity entity, int entityType)
{
if (entity == null)
{
return null;
}
else if (entity.OrganizationEntityTypeId == entityType)
{
return entity.Name;
}
else
{
return this.FindOrganizationByType(entity.Parent, entityType);
}
}

Entity Framework的LINQ提供程序必须将您的查询转换为SQL。无法将任意函数转换为SQL,这就是错误的含义:EF提供程序将只支持Where调用中的枚举或基元类型。

GroupBy示例之所以有效,是因为选择的方法是Enumerable.GroupBy而不是Queryable.GroupBy(您传递的是Func<string, Employee>Queryable.GroupBy扩展方法将采用Expression<Func<string, Employee>>)。这就是为什么最后需要AsQueryable()调用,因为您的结果是IEnumerable<Employee>

这意味着您的第二个方法将导致实体框架加载所有Employees,并且分组是在内存中完成的——这并不理想。

我最终采用了一种不同的方法,这种方法似乎效果很好。

改变了我以前使用的两种方法:

private IQueryable<Employee> EmployeesByOrganizationLevel(IQueryable<Employee> employees, int orgEntityId)
{
var results = new List<Employee>();
foreach (var employee in employees)
{
if (this.FindOrganization(employee.OrganizationEntity, orgEntityId))
{
results.Add(employee);
}    
}
return results.AsQueryable();
}
private bool FindOrganization(OrganizationEntity entity, int orgEntityId)
{
if (entity == null)
{
return false;
}
else if (entity.Id == orgEntityId)
{
return true;
}
else
{
return this.FindOrganization(entity.Parent, orgEntityId);
}
}

最新更新