Frage

Ich habe eine Hierarchie, die ich mit LinqToSql abfragen möchte:

Land -> Region -> Stadt -> ZipCode

Jedes Unternehmen hält sowohl ein Verweis auf es Eltern (zB. Region.Country) und eine Sammlung von ihm Kindern (zB. Region.Cities).

ich eifrig Last Eltern jedes Unternehmens möchte zusammen mit Ländern und Regionen, aber faul Last Städten und Postleitzahlen.

Dinge komplizieren, wird jede Einheit, bevor sie in dem Modell projiziert lokalisiert werden wird. So Country.Name Änderungen auf der Grundlage der Sprache.

Hier einige Auszüge von dem, was ich habe, so weit:

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;
}

... etc.

[TestMethod]
public void DataProvider_Correctly_Projects_Country_Spike()
{
  // Act
  Country country = dataProvider.GetCountry(1);

  // Assert
  Assert.IsNotNull(country);
  Assert.IsFalse(String.IsNullOrEmpty(country.Description));
  Assert.IsTrue(country.Regions.Count > 0);
}

Der Test schlägt fehl mit:

System.NotSupportedException. Die Methode 'System.Linq.IQueryable`1 [Beeline.EducationCompass.Model.Region] GetRegions (Int32)' hat keine unterstützte Übersetzung SQL

Wie würden Sie empfehlen ich über diese gehen? Wäre es einfacher (oder möglich), wenn jede Ebene der Hierarchie in der gleichen Tabelle anstelle von separater welche?

War es hilfreich?

Lösung

Du wirst die Linq Designer verwenden wollen, zwischen Ihren Objekten einzurichten Beziehungen. Diese bekommt man aus Schreiben join nach, nachdem sie durch die Schaffung Eigenschaften Join.

  • zwischen einem Land und seinen Regionen
  • zwischen einer Region und ihren Städten
  • zwischen einem Land und seinen Lokalisierungen
  • zwischen einer Region und ihren Lokalisierungen

Du gehst verwenden zu wollen ToList zu trennen diese Operationen Sie beabsichtigen, übersetzt in SQL werden, und diese Vorgänge beabsichtigen Sie in lokalen Code zu tun. Wenn Sie dies nicht tun, werden Sie halten sehen jene Ausnahmen „können Sie Ihre Methode in SQL nicht übersetzen“.

Du wirst auch nutzen wollen Dataload eifrig diese Eigenschaften in einigen Fällen zu laden. Hier ist mein Stab an sie.

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();
  }
}

Andere Tipps

Das ist ein klebriges Stück Code, und ich würde dies einen Mangel an entsprechenden Fähigkeiten nicht beantwortet habe fällig, wenn jemand anderes hat, aber da Sie keine Antworten hatten ...

Ich kann Ihnen sagen, was die Fehlermeldung bedeutet. Es bedeutet, dass die Funktion GetRegions kann nicht in SQL durch die LINQ to SQL-Anbieter übersetzt werden. Einige integrierte Funktionen können sein, da der Anbieter sie versteht, ist hier eine Liste . Ansonsten können Sie bieten Übersetzungen finden Sie unter hier .

In Ihrer Situation müssen Sie die Logik dieser Abfrage zu ‚Inline‘, die Logik wird die Grenze eines Funktionsaufruf nicht überqueren, weil Sie mit einem Ausdrucksbaum zu tun hat, kann die SQL Server-Rückruf nicht in der GetRegions Verfahren.

In Bezug auf die genaue Art und Weise, das zu tun, werden Sie mal ran müssen, ich habe nicht die Zeit, die Sie im Moment zu verpflichten. (Es sei denn, jemand anderes hat Zeit und Geschick?)

Viel Glück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top