2010-09-16 7 views
6

Ich habe eine LINQ to EF-Abfrage, die Daten in einer Klassenform zurückgibt. Die Klasse hat eine List<RecipeCategories> Eigenschaft, die ich füllen muss. Die RecipeCategories-Tabelle ist eine Beziehungstabelle zwischen der Rezepttabelle und der RecipeCategories-Tabelle und kann viele bis viele enthalten. Ich habe genug Informationen gefunden, um den Code kompilieren zu lassen, aber er hat Fehler zur Laufzeit und ich konnte nicht herausfinden, wie ich das richtig machen kann.Untergruppe in Liste abrufen <class> Formular

ri = (from r in recipeData.Recipes 
       where r.ID == recipeId 
       select new RecipeItem 
       { 
        Id = r.ID, 
        ProductId = r.Product.ID, 
        RecipeName = r.recipeName, 
        RecipeDescription = r.recipeDescription, 
        Servings = r.servings.HasValue ? r.servings.Value : 0, 
        CreatedDate = r.createdDate, 
        PrepTime = r.prepTime.HasValue ? r.servings.Value : 0, 
        CookTime = r.cookTime.HasValue ? r.servings.Value : 0, 
        Approved = r.approved, 
        RecipeInstructions = r.recipeInstructions, 
        RecipeIngredients = r.recipeIngredients, 
        RecipeCategories = r.RecipeCategories.Select(i => new RecipeCategoryItem { Id = i.ID, CategoryName = i.categoryName }).ToList() 
       }).First(); 

Dies ist der Fehler, den ich bekomme.

LINQ to Entities nicht das Verfahren erkennen 'System.Collections.Generic.List 1[RecipeCategoryItem] ToList[RecipeCategoryItem](System.Collections.Generic.IEnumerable 1 [RecipeCategoryItem])' Methode, und diese Methode nicht in einen Laden Ausdruck übersetzt werden kann.

Der Teil, an dem ich arbeite, ist diese Linie.

RecipeCategories = r.RecipeCategories.Select(i => new RecipeCategoryItem { Id = i.ID, CategoryName = i.categoryName }).ToList() 

RecipeCategories ist eine List<RecipeCategoryItem> Eigenschaft.

Ist was ich versuche zu tun, und wenn ja, wie?

Vielen Dank.

Antwort

11

Sie rufen ToList innerhalb dessen auf, was zu einer größeren Abfrage wird. Entfernen Sie den Aufruf von .ToList().

Das Problem ist, dass alles in Ihrer Abfrage in eine große Ausdrucksstruktur umgewandelt wird, die Entity Framework in eine SQL-Anweisung zu übersetzen versucht. "ToList" hat keine Bedeutung von einem SQL-Standpunkt aus, also sollten Sie es nirgendwo innerhalb Ihrer Abfrage nennen.

In den meisten Fällen möchten Sie ToList in Ihrer gesamten Abfrage aufrufen, bevor Sie sie zurückgeben, um sicherzustellen, dass die Abfrage ausgewertet und die Ergebnisse in den Speicher geladen werden. In diesem Fall geben Sie nur ein Objekt zurück, so dass der Aufruf an First im Wesentlichen dasselbe tut.

Wie wichtig ist es, dass RecipeCategories eine List<RecipeCategoryItem> sind? Wenn Sie stattdessen IEnumerable verwenden können, können Sie den Anruf problemlos zu ToList entfernen.

Wenn es absolut notwendig ist, dass Sie eine List haben, dann müssen Sie zuerst alle Informationen mit einer ursprünglichen Entity Framework-Abfrage und anonyme Typen (ohne Aufruf von ToList) ziehen, und konvertieren Sie dann die empfangenen Daten in das Objekt Geben Sie den gewünschten Wert ein, bevor Sie ihn zurückgeben.

Oder Sie könnten Ihre RecipeInfo Objekt Stück für Stück aus mehreren Abfragen bauen, etwa so:

var ri = (from r in recipeData.Recipes 
      where r.ID == recipeId 
      select new RecipeItem 
      { 
       Id = r.ID, 
       ProductId = r.Product.ID, 
       RecipeName = r.recipeName, 
       RecipeDescription = r.recipeDescription, 
       Servings = r.servings.HasValue ? r.servings.Value : 0, 
       CreatedDate = r.createdDate, 
       PrepTime = r.prepTime.HasValue ? r.servings.Value : 0, 
       CookTime = r.cookTime.HasValue ? r.servings.Value : 0, 
       Approved = r.approved, 
       RecipeInstructions = r.recipeInstructions, 
       RecipeIngredients = r.recipeIngredients, 
      }).First(); 
var rc = from c in recipeData.RecipeCategories 
     where c.Recipes.Any(r => r.ID == recipeId) 
     select new RecipeCategoryItem 
     { 
      Id = c.ID, CategoryName = c.categoryName 
     }; 
ri.RecipeCategories = ri.ToList(); 

Beachten Sie, dass dieses letzte Beispiel zwei Datenbankfahrten verursacht, wird aber weniger verursachen Daten über das Netzwerk gesendet werden.

+0

ich vor Ihrer zweite Art und Weise versucht hatte, aber c.Das Rezept macht keine Felder verfügbar, und ich denke, das liegt daran, dass die Beziehungstabelle nicht wirklich im Datenmodell angezeigt wird, da es sich um eine Verknüpfungstabelle zwischen Rezepten und Rezeptkategorien handelt. Ich habe es auf die erste Art und Weise versucht, wie du es gesagt hast, aber ich bin mir nicht sicher, wie ich die linq-Abfrage jetzt strukturieren soll. Das habe ich. [CODE] RecipeCategories = r.RecipeCategories.Select (i => neues RecipeCategoryItem {Id = i.ID, CategoryName = i.categoryName}) [/ CODE] – Ben

+0

Letzter Kommentar abgelaufen. Ich bekomme diesen Fehler. IEnumerable kann nicht in RecipeCategoryItems konvertiert werden – Ben

+0

@Ben: Es hört sich so an, als hätten Recipes und RecipeCategories eine Viele-zu-Viele-Beziehung? Ich habe meine Antwort entsprechend bearbeitet. Lass mich wissen, wie das für dich funktioniert. Mit dem ersten Weg, den ich gesagt habe, müssen Sie einen anonymen Typ verwenden, indem Sie 'neues RezeptItem auswählen <' zu 'neu wählen {'. Dann wäre der zweite Schritt, dieses anonyme Objekt zu nehmen und basierend auf seinen Daten ein neues Rezeptobjekt zu erstellen. – StriplingWarrior

2

Ich denke, ich habe eine Lösung für das Problem. Verwenden Sie den dynamischen Typ.

public class BoxImageViewDetailDto 
{ 
    public Guid PropertyId { get; set; } 

    public string Title { get; set; } 
    public string SubTitle { get; set; } 
    public string Description { get; set; } 
    public string SubDescription { get; set; } 

    public decimal? PropertyValue { get; set; } 
    public byte? UnitsFloor { get; set; } 

    public dynamic ImagensRowsVar { get; set; } 
    public List<ImageViewDto> ImagensRows 
    { 
     get 
     { 
      return (List<ImageViewDto>)this.ImagensRowsVar; 
     } 
    } 

    public int ImagensRowsTotal { get; set; } 
} 

CorretorDaVez.DTO.UserControls.BoxImageViewDetailDto c = (from p in entities.rlt_Property 
    join pc in entities.rlt_PropertyPicture on p.PropertyId equals pc.PropertyId 
    where p.PropertyId == propertyId 
    orderby p.CreateDate descending 
    select new CorretorDaVez.DTO.UserControls.BoxImageViewDetailDto 
    { 
     PropertyId = p.PropertyId, 
     Title = p.Title, 
     PropertyValue = p.PropertyValue, 
     Description = p.Description, 
     UnitsFloor = p.UnitsFloor, 
     ImagensRowsTotal = p.rlt_PropertyPicture.Count, 
     ImagensRowsVar = p.rlt_PropertyPicture.Select(s => new CorretorDaVez.DTO.UserControls.ImageViewDto { PropertyId = p.PropertyId, ImagePath = pc.PhotoUrl}) 
    }).FirstOrDefault(); 
0

Versuch:

 


    var ri = (from r in recipeData.Recipes 
       where r.ID == recipeId 
       select new RecipeItem 
       { 
        Id = r.ID, 
        ProductId = r.Product.ID, 
        RecipeName = r.recipeName, 
        RecipeDescription = r.recipeDescription, 
        Servings = r.servings.HasValue ? r.servings.Value : 0, 
        CreatedDate = r.createdDate, 
        PrepTime = r.prepTime.HasValue ? r.servings.Value : 0, 
        CookTime = r.cookTime.HasValue ? r.servings.Value : 0, 
        Approved = r.approved, 
        RecipeInstructions = r.recipeInstructions, 
        RecipeIngredients = r.recipeIngredients, 
        RecipeCategories = from rc in recipeData.RecipeCategories 
            where rc.Recipes.Any(r => r.ID == recipeId) 
            select new RecipeCategoryItem{ 
               Id = rc.ID, 
               CategoryName = rc.categoryName 
              } 
    ).First();