Linq To Sql возвращается из функции как IQueryable ‹T›

Хорошо, мне удалось получить следующие рабочие

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

Я пошел дальше и создал свой собственный класс (myObject), содержащий примитивы ticket_id, title, care_of_email и filename. Какие элементы я возвращаю в своем операторе linq.

Я изменил свое заявление на

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

думая, что это сделает его типизированным с помощью универсальных шаблонов, но я получаю сообщение об ошибке «Невозможно преобразовать группу методов 'AsQueryable' в неделегатный тип 'System.Linq.IQueryable'. Вы намеревались вызвать метод?»

Возможно ли то, что я пытаюсь сделать?

Должен ли класс myObject реализовывать IEnumerable или IQueryable?

Или лучше построить объект MyObject из набора результатов linq, а затем просто вернуть из функции объект MyObject

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

person Community    schedule 20.01.2009    source источник
comment
Подсказка, имена классов PascalCased.   -  person Dykam    schedule 27.09.2009


Ответы (4)


Ты имеешь в виду:

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

(обратите внимание, я немного изменил имена, чтобы они были более идиоматичными для C #)

Это «инициализатор объекта», который создает новый MyObject (для каждой записи) и назначает свойства из исходных данных. У вас был инициализатор «анонимного типа», что не то же самое. Обратите внимание, что если у вас есть конструктор, отличный от конструктора по умолчанию, вы также можете использовать что-то вроде:

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

который использует указанный конструктор, передавая предоставленные значения из исходных данных.

Тогда это будет IQueryable<MyObject>; Вам не нужно звонить .AsQueryable(). Обратите внимание, что для вашей функции было бы лучше возвращать типизированную форму (IQueryable<MyObject>), чем нетипизированную IQueryable.

person Marc Gravell    schedule 20.01.2009

Эта строка синтаксически неверна:

return ticketDetails.AsQueryable()<myObject>;

и должен прочитать

return ticketDetails.AsQueryable<myObject>();

Кроме того, вы создаете анонимные объекты с select new {, но хотите создать myObject экземпляров. Правильная реализация будет выглядеть так:

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

}

Синтаксис new SomeClass() { Property = value, ... создает экземпляр SomeClass и устанавливает свойства для заданных значений. В качестве альтернативы вы можете реализовать конструктор в классе myObject и вызвать его в операторе linq с помощью select new myObject(...).

person Community    schedule 20.01.2009

Как заявил Марк, вы не создаете экземпляры myObject при выполнении запроса. Но, кроме того, вам не нужно приводить его к IQueryable<T>, статус выбора LINQ вернет IQueryable<T>, если явное приведение к IEnumerable<T>.

Кроме того, будьте осторожны, чтобы ваш DataContext не был удален, прежде чем вы попытаетесь получить доступ к возвращаемым данным. Но я заметил, что ваш контекст не создается в методе, будьте осторожны, чтобы не поддерживать DataContext слишком долго, это объект единицы работы и не предназначен для того, чтобы оставаться открытым в течение длительных периодов времени.

person Aaron Powell    schedule 20.01.2009

Джентльмены, все это имеет смысл, если вы возвращаете только одну таблицу, но что, если нужно вернуть две или более ???

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;        
person Jake    schedule 18.03.2012