Linq To Sql从函数返回为IQueryable <t> </t>

时间:2009-01-20 11:03:22

标签: c# linq-to-sql generics ienumerable iqueryable

好的,我已成功完成以下工作

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和文件名。我在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?

或者最好从linq结果集构造对象MyObject,然后从函数返回对象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;
}

4 个答案:

答案 0 :(得分:14)

你的意思是:

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

(注意我稍微调整了一些名字,以便更多地使用C#-idiomatic)

这是一个“对象初始值设定项”,它创建一个新的MyObject(每条记录)并从源数据中分配属性。你有一个“匿名类型”初始化程序,它是不一样的。请注意,如果您有非默认构造函数,则还可以使用以下内容:

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

使用指定的构造函数,从源数据传入提供的值。

这将是IQueryable<MyObject>;您无需致电.AsQueryable()。请注意,您的函数返回键入的表单(IQueryable<MyObject>)比使用无类型的IQueryable更好。

答案 1 :(得分:8)

这一行在语法上是不正确的:

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类上实现构造函数,并使用select new myObject(...)在linq语句中调用它。

答案 2 :(得分:2)

正如Marc所说,当你的查询运行时,你并没有构建myObject的实例。但另外你不需要将其强制转换为IQueryable<T>,LINQ选择语句将返回IQueryable<T>,除非明确地转换为IEnumerable<T>

另外,在尝试访问返回的数据之前,请注意没有丢弃DataContext。但是我注意到你的上下文不是在方法中构造的,要小心你没有长时间维护DataContext,它是一个工作单元对象而不是长时间保持打开状态。

答案 3 :(得分:1)

男式, 只要您只返回单个表,这一切都有意义,但如果有两个或更多要返回该怎么办?

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;