简体   繁体   English

使用Linq to Entities的Linq表达式

[英]Linq expressions with Linq to Entities

I'm trying to wrap some repetitive code in an extension method, to clean things up a bit. 我正在尝试将一些重复的代码包装在扩展方法中,以进行一些清理。

The pattern I'm trying to avoid is checking if a string (normally a control's text value) is null/empty, and if it is, comparing it using Contains to a field in my data. 我试图避免的模式是检查字符串(通常是控件的文本值)是否为空/空,如果是,则使用“包含”将其与数据中的字段进行比较。 Obviously the field isn't hard-coded into my extension, neither is the object type. 显然,该字段没有硬编码到我的扩展中,对象类型也没有。

What I've got works perfectly in Linq to Objects, but I get the generic run-time error "LINQ to Entities does not recognize the method 'System.String Invoke(GenericQueryHelper.Customer)' method, and this method cannot be translated into a store expression." 我已经在Linq to Objects中完美地工作了,但是我遇到了一般的运行时错误“ LINQ to Entities无法识别方法'System.String Invoke(GenericQueryHelper.Customer)',该方法无法转换为商店表达。” when using an entity framework model. 使用实体框架模型时。

Here's what I have: 这是我所拥有的:

<System.Runtime.CompilerServices.Extension()>
Public Function CompareAndFilter(Of T)(source As System.Linq.IQueryable(Of T), expressionField As System.Linq.Expressions.Expression(Of System.Func(Of T, String)), compareTo As String)
    If String.IsNullOrEmpty(compareTo) Then
        Return source
    Else
        Dim compiledField As System.Func(Of T, String) = expressionField.Compile()
        Return source.Where(Function(x) compiledField.Invoke(x).Contains(compareTo))
    End If
End Function

And I also tried: 我也尝试过:

<System.Runtime.CompilerServices.Extension()>
Public Function CompareAndFilter(Of T)(source As System.Linq.IQueryable(Of T), expressionField As System.Func(Of T, String), compareTo As String)
    If String.IsNullOrEmpty(compareTo) Then
        Return source
    Else
        Return source.Where(Function(x) expressionField.Invoke(x).Contains(compareTo))
    End If
End Function

With an identical outcome... 结果相同...

Firstly, is this even possible? 首先,这有可能吗? I want my usage to look something like this: 我希望我的用法看起来像这样:

Dim results = repository.Customers.CompareAndFilter(Function(c) c.FirstName, searchText)

I do need to get this running against a SQL database really, as it is filtering results, so I don't want to be doing that in memory. 我确实需要使它真正针对SQL数据库运行,因为它正在过滤结果,所以我不想在内存中这样做。 Anyone any thoughts? 有任何想法吗?

Yes, it's possible, but it involves expression manipulation. 是的,这是可能的,但是它涉及表达式操纵。 You can either parse the expression you're given and build the new criterion expression yourself, or have LINQKit perform a tree traversal for you. 您可以解析给定的表达式并自己构建新的条件表达式 ,也可以让LINQKit为您执行树遍历。

Linq to entities does not understand how to invoke a delegate, it needs an expression to work out the SQL to generate. Linq to实体不了解如何调用委托,它需要一个表达式来计算要生成的SQL。

The following might be able to do what you're after: 以下可能会做您想要做的事情:

<System.Runtime.CompilerServices.Extension()>
Public Function CompareAndFilter(Of T)(source As System.Linq.IQueryable(Of T), expressionField As System.Linq.Expressions.Expression(Of System.Func(Of T, String)), compareTo As String)
    If String.IsNullOrEmpty(compareTo) Then
        Return source
    Else
        Return source.GroupBy(expressionField)
            .Where(Function(g) g.Key.Contains(compareTo))
            .SelectMany(Function(g) g)
    End If
End Function

GroupBy is being used to select the field specified by expressionField , then the key is checked, and the items in each group returned. GroupBy选择expressionField指定的字段,然后检查键,并返回每个组中的项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM