Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用LinqToSQL查询层次结构?_C#_Linq To Sql_Hierarchy - Fatal编程技术网

C# 如何使用LinqToSQL查询层次结构?

C# 如何使用LinqToSQL查询层次结构?,c#,linq-to-sql,hierarchy,C#,Linq To Sql,Hierarchy,我想用LinqToSql查询一个层次结构: 国家->地区->城市->ZipCode 每个实体既有对其父实体的引用(如Region.Country),也有其子实体的集合(如Region.Cities) 我想急切地加载每个实体的父实体以及国家和地区,但懒得加载城市和邮政编码 使事情复杂化的是,每个实体在投影到模型之前都要进行本地化。所以国家。名称根据语言而变化 以下是我目前掌握的一些信息片段: public IQueryable<Country> ListCountries() {

我想用LinqToSql查询一个层次结构:

国家->地区->城市->ZipCode

每个实体既有对其父实体的引用(如Region.Country),也有其子实体的集合(如Region.Cities)

我想急切地加载每个实体的父实体以及国家和地区,但懒得加载城市和邮政编码

使事情复杂化的是,每个实体在投影到模型之前都要进行本地化。所以国家。名称根据语言而变化

以下是我目前掌握的一些信息片段:

public IQueryable<Country> ListCountries()
{
  return ProjectCountry(dataContext.GetTable<ec_Country>());
}

private IQueryable<Country> ProjectCountry(IQueryable<ec_Country> query)
{
  var result = from country in query
  join localized in dataContext.GetTable<ec_CountryLocalization>() on country.CountryID equals localized.CountryID
  let regions = GetRegions(country.CountryID)
  where localized.StatusID == 4 && localized.WebSiteID == this.webSiteID
  select new Country(country.CountryID) {
    CreatedDate = country.CreatedDate,
    IsDeleted = country.IsDeleted,
    IsoCode = country.IsoCode,
    Name = country.Name,
    Regions = new LazyList<Region>(regions),
    Text = localized.Text,
    Title = localized.Title,
    UrlKey = country.UrlKey
  };

  return result;
}

private IQueryable<Region> GetRegions(Int32 countryID)
{
  var query = from r in dataContext.GetTable<ec_Region>()
  where r.CountryID == countryID
  orderby r.Name
  select r;

  return ProjectRegion(query);
}

private IQueryable<Region> ProjectRegion(IQueryable<ec_Region> query)
{
  var result = from region in query
  join localized in dataContext.GetTable<ec_RegionLocalization>() on region.RegionID equals localized.RegionID
  join country in ListCountries() on region.CountryID equals country.CountryID
  let cities = GetCities(region.RegionID)
  select new Region(region.RegionID) {
    Cities = new LazyList<City>(cities),
    Country = country,
    CountryID = region.CountryID,
    CreatedDate = region.CreatedDate,
    IsDeleted = region.IsDeleted,
    IsoCode = region.IsoCode,
    Name = region.Name,
    Text = localized.Text,
    Title = localized.Title,
    UrlKey = region.UrlKey
  };

  return result;
}
测试失败,原因是:

System.NotSupportedException:方法'System.Linq.IQueryable'1[Beeline.EducationCompass.Model.Region]GetRegions(Int32)'不支持到SQL的转换


你建议我怎么做?如果层次结构的每个级别都在同一个表中而不是在单独的表中,这会更简单(或可能)吗?

这是一段棘手的代码,如果其他人有,我不会回答这个问题,因为缺乏相关技能,但因为你没有回答

我可以告诉您错误消息的含义。这意味着LINQtoSQL提供程序无法将函数GetRegions转换为sql。一些内置函数可以是,因为提供者理解它们,下面是一个例子。否则,您可以提供翻译,请参见

在您的情况下,您需要“内联”此查询的逻辑,该逻辑不会跨越函数调用的边界,因为您处理的是表达式树,sql server无法回调到GetRegions方法中

至于确切的方法,你得试一试,我现在没有时间请你。(除非其他人有时间和技能?)


祝你好运。

你需要使用linq设计器来建立对象之间的关系。通过创建属性,您可以避免一次又一次地编写连接

  • 在一个国家和地区之间
  • 在一个地区和它的城市之间
  • 在一个国家和它的地方之间
  • 在一个区域和它的局部之间

您将要使用它来分离那些要转换为SQL的操作,以及那些要在本地代码中完成的操作。如果不这样做,您将继续看到那些“无法将您的方法转换为SQL”异常

在某些情况下,您还需要使用来急切地加载这些属性。这是我的尝试

DataLoadOptions dlo = new DataLoadOptions();
//bring in the Regions for each Country
dlo.LoadWith<ec_Country>(c => c.Regions);
//bring in the localizations
dlo.AssociateWith<ec_Country>(c => c.Localizations
  .Where(loc => loc.StatusID == 4 && loc.WebSiteID == this.webSiteID)
);
dlo.AssociateWith<ec_Region>(r => r.Localizations);

//set up the dataloadoptions to eagerly load the above.
dataContext.DataLoadOptions = dlo;

//Pull countries and all eagerly loaded data into memory.
List<ec_Country> queryResult = query.ToList();

//further map these data types to business types
List<Country> result = queryResult
  .Select(c => ToCountry(c))
  .ToList();

谢谢这看起来很有希望。我明天就试试。这种方法的一种变体很管用。为了避免让LinqToSql对每个地区发出一个查询来获取城市,我必须创建一个ToRegion(ec_region dto)和一个ToRegion允许(ec_region dto)。浅层版本创建模型,但不填充子集合(区域中的城市)。我认为,如果我的数据库使用Joe Celko的嵌套集方法,可能在单个查询中实现这一点。理论上,只需通过一次结果集即可实例化层次结构。还有其他人对此有什么想法吗?
DataLoadOptions dlo = new DataLoadOptions();
//bring in the Regions for each Country
dlo.LoadWith<ec_Country>(c => c.Regions);
//bring in the localizations
dlo.AssociateWith<ec_Country>(c => c.Localizations
  .Where(loc => loc.StatusID == 4 && loc.WebSiteID == this.webSiteID)
);
dlo.AssociateWith<ec_Region>(r => r.Localizations);

//set up the dataloadoptions to eagerly load the above.
dataContext.DataLoadOptions = dlo;

//Pull countries and all eagerly loaded data into memory.
List<ec_Country> queryResult = query.ToList();

//further map these data types to business types
List<Country> result = queryResult
  .Select(c => ToCountry(c))
  .ToList();
public Country ToCountry(ec_Country c)
{
  return new Country()
  {
    Name = c.Name,
    Text = c.Localizations.Single().Text,
    Regions = c.Regions().Select(r => ToRegion(r)).ToList()
  }
}

public Region ToRegion(ec_Region r)
{
  return new Region()
  {
    Name = r.Name,
    Text = r.Localizations.Single().Text,
    Cities = r.Cities.Select(city => ToCity(city)).ToLazyList();
  }
}