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