2011-06-03 60 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