继续this question,我有这个方法:
public IEnumerable<Splitting> Get(Guid companyId, long customerId)
{
CustomerRepository customersRep = new CustomerRepository();
var customers = customersRep.Get(companyId);
return GetQuery().Join(customers,
s => s.CustomerId,
c => c.Id,
(s, c) => new { s, c }).
Where(sc => sc.c.Id == customerId).
Select(sc => sc.s);
}
我在做的时候:
var query=Get(someGuid, someCustomerId);
query.ToList(); //This throws an exception
我得到了例外:
Unable to create a constant value of type 'MyProj.Domain.Business.Entities.Company.Customers.Customer'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
这个例外是什么,我该如何解决?
更新
GetQuery()
返回Context.CreateObjectSet<T>()
,其中T在这种情况下为Splitting
类
CustomerRepository.Get(companyId)
是:
public IEnumerable<Customer> Get(Guid companyId)
{
return GetQuery().
Where(x => x.CompanyId == companyId).
Where(x => x.IsDeleted == false).
AsEnumerable().
OrderBy(x => x.Name.IsNumeric()).
ThenBy(x => x.Name);
}
答案 0 :(得分:3)
您在IEnumerable<Splitting> Get(Guid companyId, long customerId)
中有一个延迟查询,我认为您正在尝试将其执行到范围之外。
将ToList()
添加到Select(sc => sc.s)
的末尾,您应该很高兴。这将确保查询在返回之前实际执行。
public IEnumerable<Splitting> Get(Guid companyId, long customerId)
{
CustomerRepository customersRep = new CustomerRepository();
var customers = customersRep.Get(companyId);
return GetQuery().Join(customers,
s => s.CustomerId,
c => c.Id,
(s, c) => new { s, c }).
Where(sc => sc.c.Id == customerId).
Select(sc => sc.s).
ToList();
}
答案 1 :(得分:2)
我认为问题在于您传递给customers
方法的Join
集合。此集合不是IQueryable
,而是内存集合,当您的Join
执行时,EF将首先从数据库中提取。这是一个内存中的集合,因为您在AsEnumerable()
方法中使用了IEnumerable<Customer> Get(Guid companyId)
,然后对结果进行排序。虽然这可以在LINQ to Objects中使用,但LINQ to Entities中不允许这样做,并导致您遇到异常。 (如果Get
将返回一组原始类型(如int
)而不是Customer
集合,那么它也适用于LTE,正如例外情况所示。)
现在,我发现您需要AsEnumerable()
,因为IsNumeric()
子句中的OrderBy()
方法无法转换为SQL。但是当你将结果传递给Join
时,你真的需要排序吗?您最后返回Splitting
类型的实体,如果您需要特殊排序,则必须在最终ToList()
之前的某处添加它。
所以,我会尝试省略AsEnumerable()
和排序:
public IQueryable<Customer> Get(Guid companyId)
{
return GetQuery().
Where(x => x.CompanyId == companyId).
Where(x => x.IsDeleted == false);
}
这样你就有IQueryable
。我希望这会起作用,包括Join
在内的整个查询将在数据库中执行。