2009-02-07 4 views
10

Das Grundproblem ...LinqToSql und das Mitglied Zugang nicht legal auf Typen Ausnahme

Ich habe eine Methode, die den folgenden Code ausführt:

IList<Gig> gigs = GetGigs().WithArtist(artistId).ToList(); 

Die GetGigs() -Methode wird Gigs aus meiner Datenbank über LinqToSql ...

Also, wenn GetGigs() WithArtist (artistId) .ToList() ausgeführt ich die folgende Ausnahme erhalten.

Member access 'ListenTo.Shared.DO.Artist Artist' of 'ListenTo.Shared.DO.Act' not legal on type 'System.Collections.Generic.List`1[ListenTo.Shared.DO.Act] 
Hinweis

, dass die Erweiterungsfunktion „WithArtist“ sieht wie folgt aus:

public static IQueryable<Gig> WithArtist(this IQueryable<Gig> qry, Guid artistId) 
    { 
     return from gig in qry 
       where gig.Acts.Any(act => (null != act.Artist) && (act.Artist.ID == artistId)) 
       orderby gig.StartDate 
       select gig; 
    } 

Wenn ich ersetzen die GetGigs() -Methode mit einem Verfahren, das eine Sammlung von Gigs in Code (und nicht von der DB über LinqToSQL Konstrukten) Ich bekomme NICHT die Ausnahme.

So bin ich ziemlich sicher, dass das Problem mit meinem LinqToSQl-Code und nicht die Objektstruktur ist.

Allerdings habe ich keine Ahnung, warum die LinqToSQl-Version nicht funktioniert, also habe ich den gesamten zugehörigen Code unten enthalten. Jede Hilfe wäre sehr dankbar erhalten !!

Der LinqToSQL Code ....

public IQueryable<ListenTo.Shared.DO.Gig> GetGigs() 
    { 
     return from g in DBContext.Gigs 
       let acts = GetActs(g.ID) 
       join venue in DBContext.Venues on g.VenueID equals venue.ID 
       select new ListenTo.Shared.DO.Gig 
       { 
        ID = g.ID, 
        Name = g.Name, 
        Acts = new List<ListenTo.Shared.DO.Act>(acts), 
        Description = g.Description, 
        StartDate = g.Date, 
        EndDate  = g.EndDate, 
        IsDeleted = g.IsDeleted, 
        Created  = g.Created, 
        TicketPrice = g.TicketPrice, 
        Venue  = new ListenTo.Shared.DO.Venue { 
            ID = venue.ID, 
            Name = venue.Name, 
            Address = venue.Address, 
            Telephone = venue.Telephone, 
            URL = venue.Website 
        } 

       }; 
    } 



    IQueryable<ListenTo.Shared.DO.Act> GetActs() 
    { 
     return from a in DBContext.Acts 

       join artist in DBContext.Artists on a.ArtistID equals artist.ID into art 
       from artist in art.DefaultIfEmpty() 

       select new ListenTo.Shared.DO.Act 
       { 
        ID = a.ID, 
        Name = a.Name, 
        Artist = artist == null ? null : new Shared.DO.Artist 
        { 
         ID = artist.ID, 
         Name = artist.Name 
        }, 
        GigId = a.GigID 

       }; 
    } 

    IQueryable<ListenTo.Shared.DO.Act> GetActs(Guid gigId) 
    { 
     return GetActs().WithGigID(gigId); 
    } 

ich den Code für das Gesetz, Künstler und Gig aufgenommen haben Objekte unter:

public class Gig : BaseDO 
{ 

    #region Accessors 

    public Venue Venue 
    { 
     get; 
     set; 
    } 

    public System.Nullable<DateTime> EndDate 
    { 
     get; 
     set; 
    } 

    public DateTime StartDate 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    public string Description 
    { 
     get; 
     set; 
    } 

    public string TicketPrice 
    { 
     get; 
     set; 
    } 

    /// <summary> 
    /// The Act object does not exist outside the context of the Gig, therefore, 
    /// the full act object is loaded here. 
    /// </summary> 
    public IList<Act> Acts 
    { 
     get; 
     set; 
    } 

    #endregion 
} 

public class Act : BaseDO 
{ 
    public Guid GigId { get; set; } 
    public string Name { get; set; } 
    public Artist Artist { get; set; } 
} 

public class Artist : BaseDO 
{ 
    public string Name { get; set; } 
    public string Profile { get; set; } 
    public DateTime Formed { get; set; } 
    public Style Style { get; set; } 
    public Town Town { get; set; } 
    public string OfficalWebsiteURL { get; set; } 
    public string ProfileAddress { get; set; } 
    public string Email { get; set; } 
    public ImageMetaData ProfileImage { get; set; } 

} 

public class BaseDO: IDO 
{ 
    #region Properties 

    private Guid _id; 

    #endregion 

    #region IDO Members 

    public Guid ID 
    { 
     get 
     { 
      return this._id; 
     } 
     set 
     { 
      this._id = value; 
     } 
    } 




} 

}

+0

Ich renne in diesen gleichen Fehler und in meinem Fall scheint es mit der Verwendung einer korrelierten Unterabfrage innerhalb meiner WHERE-Klausel verwandt zu sein. Wenn ich irgendwelche Informationen finde, werde ich Ihnen ein Update geben. – jpierson

Antwort

1

ich nicht sehen, alles in Ihren Klassen, um anzugeben, wie LINQ to SQL bestimmt werden soll, welche Spalte welche ist, etc.

W Bevor Sie erwarten, dass die Methode WithArtist in .NET ausgeführt oder in SQL konvertiert wird? Wenn Sie erwarten, dass es in SQL konvertiert wird, müssen Sie Ihre Gig-Klasse mit entsprechenden LINQ to SQL-Attributen dekorieren (oder Ihren Datenkontext auf andere Weise konfigurieren). Wenn Sie möchten, dass es im Code ausgeführt wird, ändern Sie einfach den ersten Parametertyp von IQueryable<Gig> in IEnumerable<Gig>.

+0

Es gibt automatisch generierte LinqToSQl-Gig-Klassen. Die oben definierte Gig-Klasse sind Schema-gesteuerte Objekte, die ich an LinqToSQl Data anpasse ... – iasksillyquestions

+0

Also ist der Gig-Typ, den Sie von GetGigs() zurückgeben, einer, den LINQ zu SQL kennt oder nicht? –

+0

@Jon: Ich weiß, dass Sie beschäftigt sind (und diese Frage ist jetzt ziemlich alt), aber gibt es eine Chance, dass Sie Ihre Antwort mit etwas Code ausarbeiten könnten .. mit einem Schwerpunkt auf dem * in SQL konvertiert werden *, Winkel. Ich habe genau das gleiche Problem hier. Ich verwende das Repository-Muster (zB GetAct()) + Pipes und Filter (zB mit Artist()) und mein Repository behandelt keine anderen * children * -Eigenschaften (zB. Gigs ist übergeordnet, Acts-Eigenschaft ist untergeordnet) , also versuchte ich die Abfrage zu manipulieren (zB WithActs()), um ein assoziiertes Kind dynamisch zurückzugeben, wenn der Verbraucher dafür codiert. Dieses Problem bringt mich um :( –

4

Ich denke, das Problem ist die "Let" -Anweisung in GetGigs. Die Verwendung von "let" bedeutet, dass Sie einen Teil der endgültigen Abfrage getrennt von der Hauptgruppe zum Abrufen definieren. Das Problem ist, dass "let", wenn es kein Skalar ist, zu einer verschachtelten Abfrage führt. Verschachtelte Abfragen sind nicht wirklich Linq zu sqls stärkstem Punkt, da sie auch verzögert ausgeführt werden. In Ihrer Abfrage platzieren Sie die Ergebnisse der verschachtelten Abfrage in die Projektion der Hauptmenge, die zurückgegeben wird, und fügen dann linq-Operatoren hinzu.

Wenn dies passiert, wird die verschachtelte Abfrage tiefer in die Abfrage eingebettet, die ausgeführt wird. Dies führt dazu, dass die verschachtelte Abfrage nicht in der äußeren Projektion der Abfrage ausgeführt wird und daher zusammengeführt werden muss in die SQL-Abfrage lief auf der DB. Dies ist nicht möglich, da es sich um eine geschachtelte Abfrage in einer Projektion handelt, die in der sql-Hauptabfrage verschachtelt ist und SQL kein Konzept wie "verschachtelte Abfrage in einer Projektion" hat, da Sie keine Elemente in einer Projektion abrufen können SQL, nur Skalare.

+0

Also wie lade ich eine Sammlung von Acts ohne zu benutzen? – iasksillyquestions

+0

Vielen Dank für Ihre Hilfe übrigens! – iasksillyquestions

+0

Sie können es so verwenden, wie Sie es tun, aber dann können Sie Abfrage-Operatoren nicht an diese Abfrage anhängen: die verschachtelte Abfrage muss auf der äußeren Projektion sein. Daher wird die Abfrage von GetGigs selbst mit der verschachtelten Abfrage ausgeführt. –

5

Ich hatte das gleiche Problem und was schien den Trick für mich zu lösen war eine Inline-statische Methodenaufruf, die zurückgegeben IQueryable <>, so dass ich diese zurückgestellte Abfrage in eine Variable gespeichert und referenzierte.

Ich denke, das ist ein Fehler in Linq zu SQL, aber es gibt zumindest eine angemessene Problemumgehung. Ich habe das noch nicht getestet, aber ich gehe davon aus, dass dieses Problem nur dann auftreten kann, wenn auf statische Methoden einer anderen Klasse innerhalb eines Abfrageausdrucks verwiesen wird, unabhängig davon, ob der Rückgabetyp dieser Funktion IQueryable <> ist. Vielleicht ist es die Klasse, die die Methode enthält, die das Problem verursacht. Wie ich schon sagte, ich konnte das nicht bestätigen, aber es lohnt sich, es zu untersuchen.

UPDATE: Nur für den Fall, dass die Lösung nicht klar ist, wollte ich es im Zusammenhang mit dem Beispiel aus dem ursprünglichen Beitrag hinweisen.

public IQueryable<ListenTo.Shared.DO.Gig> GetGigs() 
{ 
    var acts = GetActs(g.ID); // Don't worry this call is deferred 

    return from g in DBContext.Gigs 
      join venue in DBContext.Venues on g.VenueID equals venue.ID 
      select new ListenTo.Shared.DO.Gig 
      { 
       ID = g.ID, 
       Name = g.Name, 
       Acts = new List<ListenTo.Shared.DO.Act>(acts), 
       Description = g.Description, 
       StartDate = g.Date, 
       EndDate  = g.EndDate, 
       IsDeleted = g.IsDeleted, 
       Created  = g.Created, 
       TicketPrice = g.TicketPrice, 
       Venue  = new ListenTo.Shared.DO.Venue { 
           ID = venue.ID, 
           Name = venue.Name, 
           Address = venue.Address, 
           Telephone = venue.Telephone, 
           URL = venue.Website 
       } 

      }; 
} 

Beachten Sie, dass während dies das Problem bei der Hand korrigieren sollte es scheint auch, dass die latenten Handlungen Abfrage eine andere Frage zu sein, in jedem Element des Projektions zugegriffen wird, die ich separate Abfragen verursachen würde erraten würde ausgegeben werden zur Datenbank pro Reihe in der äußeren Projektion.

+1

Vielen Dank, hatte das gleiche Problem und setzt es in eine Variable in der Tat löst das Problem. Und ich stimme zu, es fühlt sich an wie ein Fehler in Linq zu SQL. – Magnus

+1

Ich habe beim Debuggen Breakpoints in meinen Extension-Methoden gesetzt und sie wurden nicht einmal getroffen. Nach dem Erstellen einer Variable für den Erweiterungsmechanismus Teil meiner Abfrage hat alles funktioniert und die Breakpoints wurden getroffen. –

+3

Ich bin gerade auf dieses Problem gestoßen und habe meine eigene vorgeschlagene Lösung über Google gefunden, die das Problem, das ich hatte, wieder gelöst hat. Ich wünschte, ich könnte sagen, es ist das erste Mal, dass ich das auf StackOverflow getan habe. – jpierson

Verwandte Themen