【问题标题】:IQueryable to List<T>可查询列表<T>
【发布时间】:2011-05-13 09:37:29
【问题描述】:

我知道 IQueryable 不会产生任何结果,而只是一个表达式生成器,我的问题是如何实际使用它来执行查询并将集合作为 List 返回以便能够将其绑定到网格上。

  IQueryable query = _campaignManager.GetCampaign(filter, values);

  // this line returns error
  List<Campaign> campaigns = query.Cast<Campaign>().ToList();

  grdCampaigns.DataSource = campaigns;
  grdCampaigns.DataBind();

更多细节:GetCampaign()

    public IQueryable GetCampaign(string filter, params object[] values)
    {
        string parameters = string.Empty;
        foreach (object obj in values)
        {
            parameters += obj.ToString() + ",";
        }

        parameters.Remove(parameters.Count() - 1, 1);

        var query = context.Campaigns.Where(filter, parameters)
           .Select("new(CampaignID,CampaignName)");

        return query;
    }

我正在使用 DynamicQueryable 进行动态 linq 查询

DynamicQueryable 的 .Select 扩展方法

     public static IQueryable Select(this IQueryable source, string selector, params object[] values)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (selector == null) throw new ArgumentNullException("selector");
        LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);
        return source.Provider.CreateQuery(
            Expression.Call(
                typeof(Queryable), "Select",
                new Type[] { source.ElementType, lambda.Body.Type },
                source.Expression, Expression.Quote(lambda)));
    }

IQueryable .Where() 扩展

       public static IQueryable Where(this IQueryable source, string predicate, params object[] values)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (predicate == null) throw new ArgumentNullException("predicate");
        LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);
        return source.Provider.CreateQuery(
            Expression.Call(
                typeof(Queryable), "Where",
                new Type[] { source.ElementType },
                source.Expression, Expression.Quote(lambda)));
    }

谢谢...

【问题讨论】:

  • 我使用实体框架 4,错误:无法将类型“DynamicClass1”转换为类型“Campaign”。 LINQ to Entities 仅支持转换实体数据模型原语类型。
  • 注意:'Campaign' 是 EF 上下文的生成实体
  • 你应该让我们看看GetCampaign()。无法成像DynamicClass1 的来源。肯定这个演员是无效的。
  • 我认为新的 Type[] 返回的是 DynamicClass1 类型...我不确定
  • @dotnetlinc 你有没有解决过这个问题我也有类似的问题,我只需要转换到任何 iEnumberable

标签: c# linq iqueryable


【解决方案1】:

使用 .NET 4.0 并稍微修改动态库,我们可以达到预期的结果:var campaigns = query.Cast&lt;dynamic&gt;().ToList(); 甚至 var campaigns = query.ToList();


操作方法如下:
变化:

public abstract class DynamicClass {

到:

public abstract class DynamicClass : System.Dynamic.DynamicObject {


这是使用修改后的库的工作代码:

var query = db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
            OrderBy("CompanyName").
            Select("New(CompanyName as Name, Phone)");

foreach (var val in query.Cast<dynamic>().ToList())
     Console.WriteLine(string.Format("Name: {0}, Phone: {1}", val.Name, val.Phone));


我们还可以在DynamicQueryable 类中添加一个重载的扩展方法:

public static IQueryable<T> Select<T>(this IQueryable source, string selector, params object[] values)
{
    return Select(source, selector, values).Cast<T>();
}

那么我们应该可以这样调用:

var query = db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
            OrderBy("CompanyName").
            Select<dynamic>("New(CompanyName as Name, Phone)");

foreach (var val in query.ToList())
    Console.WriteLine(string.Format("Name: {0}, Phone: {1}", val.Name, val.Phone));


P.S:来自MSDN

任何对象都可以隐式转换为动态类型。

所以我们应该能够在没有建议更改的情况下致电Cast&lt;dynamic&gt;()

【讨论】:

    【解决方案2】:

    IQueryable 可以是 T 类型,例如 IQueryable 查询=+CampaignManager.GetCampaign

    但由于您使用的是 IQueryable,因此您可以使用

    var enumerator= c.GetEnumerator();
                while (enumerator.MoveNext())
                {
                 //add these records to some collection say Collection or Campaign or Create any entity with Name and Id and then assign that collection to DataSource    
                }
    

    我已经试过了,你可以继续使用它。

    【讨论】:

    • 您正在通过 new{CampaignID,CampaignName} 返回一个动态类,这就是它抛出无效强制转换操作的原因......一种选择是通过反射或循环自己翻译它。
    • 如何让它返回 Campaign 对象?新广告系列(广告系列 ID、广告系列名称)?
    • 如果您使用的是 3.0 或更高版本,那么为什么不这样做: varcampaign = query..ToList(); grdCampaigns.DataSource = 广告系列; var 将作为动态变量类型工作,它允许您绑定 DynamicClass 并且在您的绑定中您仍然可以使用您已经使用的两个属性
    • var campaigns = query.Cast&lt;dynamic&gt;().ToList(); Unable to cast the type 'DynamicClass1' to type 'System.Object'. LINQ to Entities only supports casting Entity Data Model primitive types. 我正在使用 4.0.. 谢谢
    • 但是 IQueryable 中没有 ToList() 方法(不是 Iqueryable
    猜你喜欢
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    相关资源
    最近更新 更多