调用ToList()时的异常

时间:2011-06-03 02:01:20

标签: c# .net entity-framework

继续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在这种情况下为SplittingCustomerRepository.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);
    }

2 个答案:

答案 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在内的整个查询将在数据库中执行。