在另一个IQueryable源上执行表达式

时间:2014-06-20 11:26:34

标签: c# linq iqueryable

有两个具有相同字段结构的类:WebMessageWebMessageDto

我有一个可以同时使用这两个类的DataGrid。我有一个RIA服务,它只能提供WebMessageDto因为WebMessage具有导航属性而且无法序列化。

现在,DataGrid应该查询返回IQueryable<WebMessageDto>的RIA服务方法。我需要处理DataGrid的查询并在ORM的Table<WebMessage>上执行,然后将结果转换为WebMessageDto类型并将其返回给DataGrid。

我开始实现自定义IQueryable接口,我可以处理表达式。

public class WebMessageQueryContext
{
    // Executes the expression tree that is passed to it. 
    internal static object Execute(Expression expression, bool isEnumerable)
    {
        // DataContext.WebMessages is a ORM table which returns IQueryable<WebMessage>
        List<WebMessage> list = DataContext.WebMessages.Provider.Execute(expression);

        return WebMessageDto.ConvertFrom(list); // returning List<WebMessageDto>
    }
}

上面的代码将对此方法进行递归调用。我找到了microsoft的示例,其中可查询的源代码在ExpressionVisitor中发生了变化,现在我将原始源代码更改为ORM的表。

    protected override Expression VisitConstant(ConstantExpression c)
    {
        if (c.Type == typeof(WebMessageDtoQuerySource<WebMessageDto>))
            return Expression.Constant(DataContext.WebMessages);

        return c;
    }

我执行表达式时遇到异常:

Expression of type 'System.Data.Linq.Table'1[WebMessage]' cannot be used for parameter of type 'System.Linq.IQueryable'1[WebMessageDto]' of method 'Int32 Count[WebMessageDto](System.Linq.IQueryable 1 [WebMessageDto])&#39;`

没有太多关于IQueryableProviders的信息,我也不知道该怎么做......谁能回答,我能从理论上做到吗?

2 个答案:

答案 0 :(得分:1)

对不起伙计们,我错了。在编辑问题之前,我写了Select应用于IQueryable之前Where导致在内存中加载所有表行然后执行Where语句。但实际上这种行为是由自定义linq提供程序的错误实现引起的。

当我使用没有自定义linq提供程序的datagrid时,我提到SelectWhere后执行,即使在Select之前应用了Where

在我的代码中:

public IQueryable<WebMessageDto> Dtos 
{ 
    get { return db.WebMessages.Select(r => new WebMessageDto { Id = r.Id });} 
}

我的DataGrid使用Where/OrderBy/GroupBy语句查询此方法,然后转换为WebMessageDto

因此,Alex Key的答案也适用。

答案 1 :(得分:-1)

您可以使用automapper在不同类型之间进行转换。

这是getting started guide

e.g。

Mapper.CreateMap<Order, OrderDto>();
OrderDto dto = Mapper.Map<OrderDto>(order);

修改

您可以使用automapper IQueryable extensions来提供帮助。