【问题标题】:Error converting LINQ anonymous type to IList<>将 LINQ 匿名类型转换为 IList<> 时出错
【发布时间】:2013-12-17 15:37:25
【问题描述】:

我有以下 LINQ 连接:

var query = _ABC.Table
            .Join(_DEF.Table, cef => ...etc... })
            .Join(_GHI.Table, extf => ...etc...})
            .Select(jcefn=> new { XYZ = jcefn....etc...});

linq 很好,并且返回了我期望的结果(在 LINQ pad 中验证)。

我正在尝试将查询传递到具有此签名的扩展方法中:

public PagedList(IQueryable<T> source, int pageIndex, int pageSize)
{ ... }

所以我认为这是可以接受的:

var FPaged = new PagedList<MyObject>(query.ToList(), pageIndex, pageSize);

但这显然不会让编译器满意。意思是:

参数 1:无法从 'System.Collections.Generic.List' 转换为 'System.Linq.IQueryable 等。

很明显我需要更改我的 linq 匿名类型,但不确定要更改为什么?

请注意,为了简洁起见,我没有包含很多代码,因为我认为它不需要理解,但如果需要,我很乐意编辑它。

谢谢

【问题讨论】:

  • 不要在查询中调用 ToList(),抱怨它不能从 IQueryable 转换为 List。
  • 对??这就是我首先做的,它告诉我:无法从 'System.Linq.IQueryable' 转换为 'System.Linq.IQueryable'

标签: c# linq


【解决方案1】:

是的 - query.ToList() 将返回一个 List&lt;T&gt;,它没有实现 IQueryable&lt;T&gt;。实际上,ToList() 会使分页变得不那么有用,因为它会在将整个表提取到内存后本地完成。

只需摆脱对ToList() 的呼叫,它可能会很好。

编辑:好的,如果由于匿名类型而不能正常工作,那么添加 ToList 呼叫将无济于事。您要么想要使用投射到IQueryable&lt;MyObject&gt; 的查询,要么如果您真的想要匿名类型的分页查询,您可以添加一个扩展方法:

public static class PagingExtensions
{
    public static PagedList<T> Paginate<T>(this IQueryable<T> source,
                                           int pageIndex, int pageSize)
    {
        return new PagedList<T>(source, pageIndex, pageSize);
    }
}

那么你可以使用:

// TODO: Use a more sensible variable name
var FPaged = query.Paginate(pageIndex, pageSize);

【讨论】:

  • 对??这就是我首先做的,它告诉我:无法从 'System.Linq.IQueryable' 转换为 'System.Linq.IQueryable'
  • @user1278561 try var FPaged = new PagedList(query.ToList(), pageIndex, pageSize); 您指定 PagedList 将采用 MyObject 类型,但它是匿名类型。
  • 那是因为 MyObject 与匿名类型不同。要么选择它,要么最初将其设为 MyObject 而不是匿名类型。否则就像尝试将字符串插入 int 一样。
  • 当然...MyObj 与匿名类型不同。但是你因为选择它而失去了我......你的意思是把它投影为 MyObj 而不是匿名的?
  • 那个或者使用.Select()来转换元素,这是一个更糟糕的主意。
【解决方案2】:

摆脱 ToList()。你需要一个 IQueryable 而不是 IList

var FPaged = new PagedList(query, pageIndex, pageSize);

【讨论】:

    【解决方案3】:

    PagedList 需要IQueryable&lt;MyQuery&gt;。您的查询对象的类型为IQueryable&lt;anonymous-type&gt;。要获得IQueryable&lt;MyQuery&gt;,您需要将您的选择更改为:

    var query = _ABC.Table
                .Join(_DEF.Table, cef => ...etc... })
                .Join(_GHI.Table, extf => ...etc...})
                .Select(jcefn=> new MyObject(){ XYZ = jcefn....etc...});
    

    您不需要 .ToList() 将其转换为 IQueryable,它已经是。

    但是,如果您确实想在将 IQueriable 传递给函数之前执行并缓存它,您可以这样做

    var cachedQuery = query.ToList();
    var FPaged = new PagedList<MyObject>(cachedQuery.AsQueryAble<MyObject>(), pageIndex, pageSize);
    

    在大多数情况下,这不是您想要的。 PagedList 很可能需要一个 IQueryable,因为它只会检索特定页面当前需要的部分数据,而将其余可能巨大的数据集留在数据库中的查询后面。

    但如果您真的只想检索一次所有数据,然后再将其转换为 PagedList,那么这是可行的方法。然后,您还可以在其他地方重用 cachedQuery,而不会导致另一个数据库检索。

    【讨论】:

    • OHHHHH...我不觉得很笨吗!这就是我所缺少的。 Select(jcefn=> new **MyObject()**{ XYZ = jcefn....etc...});看到我没有意识到我可以将它从匿名更改为选择中的对象。我虽然我必须在选择后进行转换。我知道对你们来说可能是一个愚蠢的菜鸟。谢谢!
    猜你喜欢
    • 2012-01-20
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 2012-06-26
    • 2012-05-01
    • 2020-04-18
    相关资源
    最近更新 更多