【问题标题】:How to create Prepend extension method for IQueryable<T> which is compatible with Linq to Entities 4.0?如何为与 Linq to Entities 4.0 兼容的 IQueryable<T> 创建 Prepend 扩展方法?
【发布时间】:2010-12-10 16:20:04
【问题描述】:

对于使用 LINQ to Entities 4.0 的项目,我有一个设置,我需要返回一个带有(常量)值的查询。如果我用 SQL 编码,它看起来像这样:

select 0 as ID, 'default' as Name
union
select ID, Name from X

对于这个项目,我想为 IQueryable 创建一个通用扩展方法,它接受一个常量值,返回一个带有常量值作为结果的查询。该过程不应触发枚举,因为我不希望查询触发数据库命中,除非应用程序中的其他代码实际针对查询进行枚举。

理想情况下,我希望 IQueryable 结果可连接到其他 Linq to Entities 查询并可由 L2E 提供商处理。

我尝试了几种变体,但意识到它们将触发枚举而不是添加到查询中。我最近的尝试扩展了查询而不枚举(根据需要),但返回错误:

    public static IQueryable<T> Prepend<T>(
        this IQueryable<T> query
        , T value
        )
    {
        return query
            .Where(t => false).DefaultIfEmpty(value)
            .Concat(query);
    }

错误是,“无法创建‘OCEAN.B​​usiness.Pocos.ExclusionIncomeType’类型的常量值。在此上下文中仅支持原始类型(‘例如 Int32、String 和 Guid’)。”。

我尝试搜索类似的概念,包括附加一个值,但无济于事。

想法?

【问题讨论】:

  • 您是否尝试过使用实际的Unionquery.Union(new[] {value})?我知道 Linq-to-SQL 不喜欢这样,但也许 Linq-to-Entities 可以处理它?

标签: entity-framework .net-4.0 linq-to-entities iqueryable


【解决方案1】:

您可以使用iterator 创建一个新的IEnumerable&lt;T&gt; 实例,该实例首先返回您的默认值:

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> sequence, T value) 
{
    yield return value;
    foreach (var item in sequence)
    {
        yield return item;
    }
}

这将创建一个枚举器,它将首先返回您的默认项目,然后通过查询进行枚举。

【讨论】:

  • 听起来很有希望。理想情况下,我希望 IQueryable 结果可连接到其他 Linq to Entities 查询并可由 L2E 提供程序处理。但是,这仍然可以解决我的基本需求。
  • 经过反思,这在技术上并不匹配,因为 IEnumerable 没有实现 IQueryable(尽管情况正好相反)。但是,我可能能够解决我的问题。
  • // 这让我半途而废。最终解决方案: private static IEnumerable PrependEnumerator(this IEnumerable sequence, T value) { yield return value; foreach (var item in sequence) { yield return item; } } public static IQueryable Prepend( this IQueryable query , T value ) { return query.PrependEnumerator(value).AsQueryable(); }
【解决方案2】:

最终答案:

    private static IEnumerable<T> PrependEnumerator<T>(this IEnumerable<T> sequence, T value)  
    { 
        yield return value; 
        foreach (var item in sequence) 
        { 
            yield return item; 
        } 
    } 

    public static IQueryable<T> Prepend<T>(
        this IQueryable<T> query
        , T value
        )
    {
        return query.PrependEnumerator(value).AsQueryable();
    }

【讨论】:

    【解决方案3】:
    private static IEnumerable<T> PrependEnumerator<T>(
        this IEnumerable<T> sequence, 
        T value
        ) 
    { 
        yield return value; 
        foreach (var item in sequence) { yield return item; } 
    } 
    public static IQueryable<T> Prepend<T>( 
        this IQueryable<T> query , 
        T value 
        ) 
    { 
        return query.PrependEnumerator(value).AsQueryable(); 
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      相关资源
      最近更新 更多