【问题标题】:Workarounds for using custom methods/extension methods in LINQ to Entities在 LINQ to Entities 中使用自定义方法/扩展方法的解决方法
【发布时间】:2011-02-01 19:32:14
【问题描述】:

我已经定义了一个进行数据库交互的 GenericRepository 类。

 protected GenericRepository rep = new GenericRepository();

在我的 BLL 课程中,我可以像这样查询数据库:

public List<Album> GetVisibleAlbums(int accessLevel)
{
    return rep.Find<Album>(a => a.AccessLevel.BinaryAnd(accessLevel)).ToList();  
}  

BinaryAnd 是一种扩展方法,它逐位检查两个 int 值。例如AccessLevel=5 => AccessLevel.BinaryAnd(5)AccessLevel.binaryAnd(1) 都返回 true。

但是我不能在我的 LINQ 查询中使用这种扩展方法。我收到如下运行时错误:
LINQ to Entities does not recognize the method 'Boolean BinaryAnd(System.Object, System.Object)' method, and this method cannot be translated into a store expression.

还尝试将其更改为自定义方法,但没有运气。有哪些解决方法?

我是否应该获取所有专辑,然后通过 foreach 循环迭代它们并选择与 AccessLevels 匹配的那些?

【问题讨论】:

    标签: linq c#-4.0 linq-to-entities extension-methods


    【解决方案1】:

    我意识到这已经有一个公认的答案,我只是想我会发布这个以防有人想尝试编写一个 LINQ 表达式拦截器。

    所以...这是我为制作可翻译的自定义扩展方法所做的:Code Sample

    我不认为这是一个已完成的解决方案,但它有望为任何有勇气完成它的人提供一个良好的起点。

    【讨论】:

    • 我发现在扩展方法.Where(p=&gt; p.Key == 25) 中给出了关于 p 未绑定的错误。所以我不得不像Expression&lt;Func&lt;PropertyHistory, bool&gt;&gt; exp = (p) =&gt; p.Key ==25; 这样声明lambda,然后在.Where(exp) 中使用它。考虑到扩展的可重用性,它仍然很棒。如果你想发布你的答案,这里有一个开放的赏金。如果您对代码进行更新,我将非常感谢您发表评论。我认为这值得一个 codeplex 项目。 stackoverflow.com/questions/10826275/…
    • @AaronLS 我确实更新了它。我想为表达式翻译添加对编译查询和自定义扩展方法的支持。不确定这是否是一个好的解决方案,我只是在尝试一些东西。你可以在这里查看:Code
    • 这太棒了,你应该把它放在nuget中
    【解决方案2】:

    您只能在使用实体框架和在IQueryable&lt;T&gt; 上查询时使用core extension methods and CLR methods defined for your EF provider。这是因为查询直接转换为 SQL 代码并在服务器上运行。

    您可以流式传输整个集合(使用.ToEnumerable()),然后在本地查询它,或将其转换为可由您的提供程序直接转换为 SQL 的方法。

    话虽如此,basic bitwise operations are supported

    当操作数是数字类型时,按位 AND、OR、NOT 和 XOR 运算符也映射到规范函数。

    因此,如果您将其重写为不使用方法,而直接对值进行按位运算,它应该可以根据需要工作。尝试以下方法:

    public List<Album> GetVisibleAlbums(int accessLevel)
    {
        return rep.Find<Album>(a => (a.AccessLevel & accessLevel > 0)).ToList();  
    }
    

    (我不确定您当前的扩展方法究竟是如何工作的 - 上面将检查是否有任何标志返回 true,这似乎与您的陈述相匹配...)

    【讨论】:

    • 谢谢里德。猜猜这是唯一的方法。
    • @Kamyar:这应该只是不使用扩展方法并将实际代码放入查询中的问题 - 请参阅我的编辑。
    【解决方案3】:

    有一些方法可以在 EF 将其转换为 SQL 之前更改 linq 查询,此时您必须将“外国”方法转换为 EF 可翻译的构造。

    查看我的上一个问题How to wrap Entity Framework to intercept the LINQ expression just before execution? 和我的EFWrappableFields extension,它对包装字段执行此操作。

    【讨论】:

      猜你喜欢
      • 2015-06-06
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      相关资源
      最近更新 更多