我写了以下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'是一组ISOCountry对象,显式创建并作为IQueryable&lt; ISOCountry&gt;返回。 (ISOCountry只是两个字符串的对象,isoCountryCode和Name)。竞争对手是IQueryable&lt;竞争对手&gt;虽然我从头创建了对象并使用了LINQ数据映射装饰器,但它通过LINQ to SQL绑定到数据库表。
由于某种原因,当系统尝试执行时,此查询会导致堆栈溢出。我不知道为什么,我已经尝试修剪Distinct,使用'select c'返回两个字符串的匿名类型,但都会导致溢出。 e.CountryID值是从一个下拉列表中填充的,该下拉列表本身是从IQueryable&lt; ISOCountry&gt;填充的,所以我知道这些值是合适的,但即使不是,我也不希望堆栈溢出。
为什么会发生溢出或为什么会发生?
根据要求,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();
答案 0 :(得分: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 .Contains()语句中使用。因此,如果要将本地序列与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列表上传到数据库,那就更好了。一旦你这样做,你就可以在最初设想的时候触发查询。