2011-06-03 71 views
0

至于继续this question的时候,我有这样的方法:异常调用ToList()

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. 

这种例外情况如何,我该如何解决?

UPDATE:
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); 
    } 
+1

什么是'GetQuery()'?你可以显示'GetQuery'和'CustomerRepository.Get'的代码吗? – 2011-06-03 02:28:14

+0

@Alex Aza:我更新了问题。 – Naor 2011-06-03 15:37:30

+0

这与'ToList()'没有任何关系。如果你使用'Count()'或者迭代一个'foreach',你会得到相同的异常。 – 2011-06-03 18:38:32

回答

1

我觉得现在的问题是你customers收集您传递到Join方法。这个集合不是IQueryable,而是一个内存集合,当你的Join被执行时,EF将首先从数据库中提取内存。这是一个内存集合,因为您在IEnumerable<Customer> Get(Guid companyId)方法中使用AsEnumerable(),然后对结果进行排序。虽然这可以在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在内的整个查询将在数据库中执行。

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(); 
} 
+0

“延迟查询”是什么? – Naor 2011-06-03 02:17:47

+0

表示查询在使用时评估,而不是在定义时评估。例如,在EF中,可以跨多个方法动态构建查询,然后在完成时执行一次,这样更有效。 [这是一个快速浏览](http://roque-patrick.com/windows/final/bbl0392.html)。 – ataddeini 2011-06-03 02:23:45

+0

这不起作用 - 我得到同样的例外。 – Naor 2011-06-03 15:30:38