2017-02-10 3 views
1

ich ein paar Klassen,LINQ verzögertes Laden und die Schaffung neues Objekts

public class Album 
{ 
    public int AlbumId { get; set; } 
    public string Title { get; set; } 
    public Genre genre { get; set; } 
    public virtual Artist artist { get; set; } 
} 

public class Artist 
{ 
    public int ArtistId { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Album> albums { get; set; } 
} 

public class ArtistResponse 
{ 
    public int ArtistId { get; set; } 
    public string Name { get; set; } 
} 

public class AlbumResponse 
{ 
    public int AlbumId { get; set; } 
    public string Title { get; set; } 
    public Genre genre { get; set; } 
    public ArtistResponse artist { get; set; } 
} 

Ich versuche, alle Alben mit Künstlern zum Download, und senden Sie es mit AlbumResponse. Ich habe einen Ausdruck LINQ

return ctx.Albums.Include(i => i.artist).Select(i => new AlbumResponse 
      { 
       AlbumId = i.AlbumId, 
       artist = new ArtistResponse { Name=i.artist.Name, ArtistId=i.artist.ArtistId}, 
       genre = i.genre, 
       Title = i.Title 
      }).ToList(); 

Also ich bin auch ‚Künstler‘ von „include()“ und dann neuen AlbumResponse schaffen, wo ich neue ArtistResponse erstellen. Leider funktioniert es nicht. Es löst eine InvalidOperationException aus. "i.artist.ArtistId" ist ein Null, ich weiß nicht warum, ohne ArtistId-Initialisierung funktioniert alles gut, nur "Name = i.artist.Name" funktioniert einwandfrei.

Wie hänge ich ArtistId an 'artist' in 'AlbumResponse' an? Ausnahme: "Die Umwandlung in Werttyp 'System.Int32' ist fehlgeschlagen, da der materialisierte Wert null ist. Entweder der generische Parameter des Ergebnistyps oder die Abfrage muss einen Nullwerttyp verwenden." Klassen Album und Interpret sind in Datenbank, AlbumId und ArtistId nicht nullfähig. ArtistResponse und AlbumResponse sind nur „extra“ Klassen für das Hinzufügen oder aus der Datenbank bekommen info, so ArtistId und AlbumId in „* Response“ sind ints nur

Antwort

3

Wenn die ArtistId Spalte der artist Navigationseigenschaft ein Nullable<int> und die Art der ist ArtistId Eigenschaft des ArtistResponse Typ ist int sollten Sie überprüfen, ob ein Wert zurückgegeben wird:

return ctx.Albums.Include(i => i.artist).Select(i => new AlbumResponse 
{ 
    AlbumId = i.AlbumId, 
    artist = new ArtistResponse { Name = (i.artist != null) ? i.artist.Name : string.Empty, ArtistId = (i.artist != null && i.artist.ArtistId.HasValue) ? artist.ArtistId.Value : 0 }, 
    genre = i.genre, 
    Title = i.Title 
}).ToList(); 

Dies ist natürlich nur eine Vermutung, da Sie havent't die Definitionen Ihrer Typen geschrieben, noch die tatsächliche Fehlermeldung Sie bekommen .

Edit:

Was passiert, wenn Sie die Art der ArtistId Eigenschaft des ArtistResponse Typ Nullable<int> (int?) ändern:

public class ArtistResponse 
{ 
    public Nullable<int> ArtistId { get; set; } 
    public string Name { get; set; } 
} 
+0

Dies funktioniert nicht, es zeigt Fehler auf "HasValue", "int enthält keine Definition für hasValue ...". – Pawel

+0

Versuchen Sie, die ArtistId-Eigenschaft der ArtistResponse-Klasse laut meiner Bearbeitung auf Null zu setzen. – mm8

+0

Es funktioniert jetzt :) aber ich verstehe nicht wirklich warum ... Könnten Sie es bitte erklären? – Pawel

1
return ctx.Albums.Include(i => i.artist).Select(i => new AlbumResponse 
      { 
       AlbumId = i.AlbumId, 
       artist = new ArtistResponse { Name=i.artist.Name, ArtistId=i.artist.ArtistId ?? 0(or Guid.NewGuid() << or this if you decide to use guid type)}, 
       genre = i.genre, 
       Title = i.Title 
      }).ToList(); 

Sie haben eine eindeutige Nummer zuweisen/Schlüssel zu Ihrer Künstler-ID, wenn Sie das nicht auf Null setzen möchten. new guid vielleicht? du musst einen Weg finden, eine einzigartige int id zu erstellen.

1

Sie können, ich sage nicht, dass Sie ohne vollständiges Wissen, eine unvollständige Projektion haben. Entity ist irgendwie seltsam in Bezug auf Daten, da es nicht für den Gebrauch außerhalb des Tors realisiert wird, bis es ein offizielles Objekt ist. ZB: Ihre Extensionssyntax für wo, select und andere funktionieren noch nicht, da das Objekt noch nicht realisiert wurde.

Vielleicht möchten Sie als etwas so einfach versuchen:

return ctx.Albums.Include(i => i.artist) 

.ToList()

.Select(i => new AlbumResponse 
      { 
       AlbumId = i.AlbumId, 
       artist = new ArtistResponse { Name= i?.artist?.Name ?? String.Empty, ArtistId=i?.artist?.ArtistId ?? 0}, 
       genre = i.genre, 
       Title = i.Title 
      }).ToList(); 

Else die Projektion nicht realisiert werden kann es Navigationseigenschaft 'Künstler' ist. ToList() ist der Weg des armen Mannes, eine Projektion schnell zu realisieren und im Wesentlichen zu sagen: ".NET ist als legitime Objektsammlung jetzt in Ordnung". Sie können andere Erweiterungen verwenden, die ich glaube, wie "First" glaube ich auch.Dies ist nur eine Vermutung, aber ich weiß, dass ich eine Zeit lang mit EF gearbeitet habe und "Erkenntnis" bei Ladeereignissen, Mathe und anderen Dingen oft der Schuldige ist. Oder es könnte sein, wie andere gesagt haben, dass Sie einfach einen Nullbezug auf die Navigation bekommen und es explodiert. Ich habe einen Pseudocode mit einem?. Bedingungsoperator (überprüft grundsätzlich die Kette auf Nullen ohne zu blasen, wenn der Elternteil ebenfalls Null ist) und dann einen zusammenwachsenden Nulloperator '??' zu sagen, wenn diese Sache Null ist, einen Standard zuweisen.

Verwandte Themen