c# – 在我的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’是一组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列表上传到数据库,那就更好了.一旦你这样做,你就可以在最初设想的时候触发查询.

点赞