5 Stimmen

Linq To Sql Rückgabe von Funktion als IQueryable<T>

Ok, ich habe es geschafft, folgendes zum Laufen zu bringen

public IQueryable getTicketInformation(int ticketID)
{
    var ticketDetails = from tickets in _context.tickets
        join file in _context.file_objects on tickets.ticket_id equals file.source_id
        where tickets.ticket_id == ticketID
        select new { tickets.ticket_id, tickets.title, tickets.care_of_email, file.filename };

    return ticketDetails.AsQueryable();
}

Ich habe meine eigene Klasse (myObject) erstellt, die die Primitive enthält ticket_id, title, care_of_email und filename. Das sind die Elemente, die ich in meiner Linq-Anweisung zurückgeben werde.

Ich habe meine Aussage wie folgt geändert

public IQueryable<myObject> getTicketInformation(int ticketID)
{
    var ticketDetails = from tickets in _context.tickets
        join file in _context.file_objects on tickets.ticket_id equals file.source_id
        where tickets.ticket_id == ticketID
        select new { tickets.ticket_id, tickets.title, tickets.care_of_email, file.filename };

    return ticketDetails.AsQueryable()<myObject>;
}

Ich dachte, dass es dadurch mit Generika typsicher wird, aber ich erhalte den Fehler "Die Methodengruppe 'AsQueryable' kann nicht in den nicht delegierten Typ 'System.Linq.IQueryable' konvertiert werden. Beabsichtigen Sie, die Methode aufzurufen?"

Ist das, was ich zu tun versuche, überhaupt möglich?

Muss die myObject-Klasse IEnumerable oder IQueryable implementieren?

Oder ist es am besten, das Objekt MyObject aus dem Linq Resultset zu konstruieren und dann nur aus der Funktion das Objekt MyObject zurückgeben

public myObject getTicketInformation(int ticketID) 
{

    ....linq statement....
    myObject o = null;

    foreach (obj in linqstatemt)
    {
        o = new myObject();
        o.ticket_id = obj.ticket_id
        .......
    }
    return o;
}

0 Stimmen

Hinweis: Klassennamen werden in PascalCase geschrieben.

14voto

Marc Gravell Punkte 970173

Sie meinen:

select new MyObject { TicketId = tickets.ticket_id,
     Title = tickets.title, ...};

(Anmerkung: Ich habe die Namen leicht geändert, um sie C#-idiomatischer zu machen)

Dies ist ein "Objektinitialisierer", der ein neues MyObject (pro Datensatz) und ordnet die Eigenschaften aus den Quelldaten zu. Was Sie hatten, war ein "anonymer Typ"-Initialisierer, was nicht dasselbe ist. Beachten Sie, dass, wenn Sie einen Nicht-Standard-Konstruktor haben, könnten Sie auch etwas wie verwenden:

select new MyObject(tickets.ticket_id, tickets.title);

die den angegebenen Konstruktor verwendet und die übergebenen Werte aus den Quelldaten übernimmt.

Dies wird dann IQueryable<MyObject> ; Sie müssen nicht anrufen .AsQueryable() . Beachten Sie, dass es für Ihre Funktion besser wäre, die getippte Form zurückzugeben ( IQueryable<MyObject> ) als die untypisierte IQueryable .

8voto

David Schmitt Punkte 56455

Diese Zeile ist syntaktisch falsch:

return ticketDetails.AsQueryable()<myObject>;

und sollte lauten

return ticketDetails.AsQueryable<myObject>();

Außerdem erstellen Sie anonyme Objekte mit der select new { , aber Sie wollen eine myObject Instanzen. Eine korrekte Implementierung würde wie folgt aussehen:

public IQueryable<myObject> getTicketInformation(int ticketID)
{

    return from tickets in _context.tickets
        join file in _context.file_objects on tickets.ticket_id equals file.source_id
        where tickets.ticket_id == ticketID
        select new myObject() { 
            ticket_id = tickets.ticket_id,
            title = tickets.title, 
            care_of_email = tickets.care_of_email, 
            filename = file.filename
        };

}

El new SomeClass() { Property = value, ... Syntax erzeugt eine SomeClass Instanz und setzt die Eigenschaften auf die angegebenen Werte. Alternativ könnte man einen Konstruktor für die Instanz myObject Klasse und rufen sie in der Linq-Anweisung mit select new myObject(...) .

2voto

Aaron Powell Punkte 24630

Wie Marc sagte, konstruieren Sie keine Instanzen von myObject wenn Ihre Abfrage ausgeführt wird. Aber zusätzlich müssen Sie es nicht in eine IQueryable<T> gibt eine LINQ select-Anweisung eine IQueryable<T> es sei denn, sie werden ausdrücklich in eine IEnumerable<T> .

Achten Sie auch darauf, dass Ihr DataContext nicht entsorgt wurde, bevor Sie versuchen, auf die zurückgegebenen Daten zuzugreifen. Aber ich habe bemerkt, dass Ihr Kontext nicht in der Methode konstruiert wird. Achten Sie darauf, dass Sie einen DataContext nicht zu lange aufrechterhalten, da es sich um ein Unit-of-Work-Objekt handelt, das nicht für lange Zeiträume offen gehalten werden soll.

1voto

Jake Punkte 169

Meine Herren, Es macht alles Sinn, solange Sie nur eine Tabelle zurückgeben, aber was ist, wenn zwei oder mehr zurückgegeben werden müssen?

RPDTDataContext smdt = new RPDTDataContext();
var projectedUsers = smdt.SM_Users.Join(
        smdt.SM_CTSGroups, u => u.CtsGroupID, c => c.id, 
        (u, c) => new { CTSGroup = c.Name, UserName = u.Name, u.EmpID, u.Email });
return projectedUsers;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X