2010-04-20 58 views
4

我已經寫了下面的LINQ查詢:追查一個堆棧溢出錯誤在我的LINQ查詢

IQueryable<ISOCountry> entries = 
    (from e in competitorRepository.Competitors 
    join c in countries on e.countryID equals c.isoCountryCode 
    where !e.Deleted 
    orderby c.isoCountryCode 
    select new ISOCountry() { isoCountryCode = e.countryID, Name = c.Name } 
).Distinct(); 

目的是通過檢索發現該系統中的競爭對手所代表的國家名單。 'countries'是一個顯式創建並作爲IQueryable返回的ISOCountry對象數組(ISOCountry是隻有兩個字符串的對象,即isoCountryCode和Name)。競爭對手是一個IQueryable <競爭者>它通過LINQ to SQL綁定到數據庫表,儘管我從頭創建了對象並使用了LINQ數據映射裝飾器。

由於某種原因,當系統嘗試執行該查詢時,此查詢會導致堆棧溢出。我不知道爲什麼,我試着修剪Distinct,使用'select c'返回一個匿名類型的兩個字符串,但都導致溢出。 e.CountryID值是從下拉菜單中填充的,該下拉菜單本身是由IQueryable> IQueryable>填充的,所以我知道這些值是合適的,但即使不是這樣,我也不會指望堆棧溢出。

爲什麼溢出正在發生或爲什麼會發生?對於ISOCountry

按照要求,代碼:

public class ISOCountry 
{ 
    public string isoCountryCode { get; set; } 
    public string Name { get; set; } 
} 

它是從靜態的工具類初始化這樣:

public static IQueryable<ISOCountry> GetCountryCodes() 
    { 
     // ISO 3166-1 country names and codes from http://opencountrycodes.appspot.com/javascript 
     ISOCountry[] countries = new ISOCountry[] { 
      new ISOCountry { isoCountryCode= "AF", Name= "Afghanistan"}, 
      new ISOCountry { isoCountryCode= "AX", Name= "Aland Islands"}, 
      new ISOCountry { isoCountryCode= "AL", Name= "Albania"}, 
      new ISOCountry { isoCountryCode= "DZ", Name= "Algeria"}, 
      new ISOCountry { isoCountryCode= "AS", Name= "American Samoa"}, 
      ... 
      new ISOCountry { isoCountryCode= "YE", Name= "Yemen"}, 
      new ISOCountry { isoCountryCode= "ZM", Name= "Zambia"}, 
      new ISOCountry { isoCountryCode = "ZW", Name = "Zimbabwe"} 
     }; 
     return countries.AsQueryable(); 
    } 

如何,我終於得到它的工作,見下文......我仍然對原始查詢的具體錯誤感到好奇,我確信我之前做過類似的事情。

IList<string> entries = competitorRepository.Competitors.Select(c=>c.CountryID).Distinct().ToList(); 
IList<ISOCountry> countries = Address.GetCountryCodes().Where(a => entries.Contains(a.isoCountryCode)).ToList(); 
+2

請發佈您的代碼爲ISOCountry;具體來說,屬性'isoCountryCode'看起來像什麼? – 2010-04-20 15:07:40

+1

這個國家的表格實體是一個自我引用的實體嗎? – James 2010-04-20 15:25:34

+0

@詹姆斯,不,這是一個直接IQueryable的ISOCountry初始化如此:'IQueryable countries = AddressUtils.GetCountryCodes();' – Lazarus 2010-04-20 15:28:48

回答

2

也許我瘋了,但你的實用程序類不應該輸出IQueryable列表。您正在創建一個看起來像的本地序列,它應該是可查詢的。最終,IQueryable列表應該由您的datacontext進行分析。如果實用程序類創建列表,應返回(最有可能)數組或一個IEnumerable,例如:

public static readonly ISOCountry[] CountryCodes = new ISOCountry[] { 
     new ISOCountry { isoCountryCode= "AF", Name= "Afghanistan"}, 
     new ISOCountry { isoCountryCode= "AX", Name= "Aland Islands"} 
     ... 
    }; 

本地序列只能在一個IQueryable。載有()語句中使用。所以,如果你想用你的IQueryable序列「串聯」你的本地序列,你必須強制IQueryable激發一條SQL語句,並從數據庫中獲取它所表示的記錄。要做到這一點,你所要做的就是迭代以某種方式IQueryable的記錄:

IList<Competitor> competitorRecords = competitorRepository 
    .Competitors 
    .Where(m => !m.Deleted) 
    .OrderBy(m => m.countryId) 
    .ToList(); //This fires the SQL statement 

一旦你鉤住從數據庫中的記錄,你可以創建你的ISOCountry記錄列表。同樣,由於這個列表不是來自你的datacontext,它不應該是一個IQueryable列表。相反,試試這個:

IList<ISOCountry> = competitorRecords 
    .Join(CountryCodes, key1 => key1.countryId, key2 => key2.isoCountryCode, (competitors, codes) => new ISOCountry { isoCountryCode = competitors.countryId, Name = codes.Name }) 
    .ToList(); 

這會工作,但你可能從數據庫中攫取不必要的記錄。如果您可以將ISOCountry列表上傳到數據庫,情況會更好。一旦你這樣做了,你就能夠按照你最初設想的那樣開始查詢。

+0

你可能對IQueryable返回是正確的,這個實用函數在其他地方使用,最初被設計爲從數據庫中提取,因此IQueryable(可能是我對界面的不完全理解)。我現在已經設法完成功能,將其分解爲部分和使用IList,但我仍然很好奇爲什麼原始查詢不起作用,我認爲它應該或應該至少提供更好的錯誤消息;) – Lazarus 2010-05-11 11:52:19