Vb.net LINQ中的自定义函数到实体?如何编写可接受的代码?

Vb.net LINQ中的自定义函数到实体?如何编写可接受的代码?,vb.net,entity-framework,linq-to-entities,Vb.net,Entity Framework,Linq To Entities,使用my simple函数会导致应用程序退出所有嵌套的Using块,并将控制返回到最外层的End Using语句。但内置函数可以正常工作。如何绕过这种奇怪的局面 Public Shared ReadOnly GlobalSettingsKeyList As New HashSet(Of String) Public Shared Function IsGlobalSetting(key As String) As Boolean Return GlobalSettingsKeyList

使用my simple函数会导致应用程序退出所有嵌套的Using块,并将控制返回到最外层的End Using语句。但内置函数可以正常工作。如何绕过这种奇怪的局面

Public Shared ReadOnly GlobalSettingsKeyList As New HashSet(Of String)

Public Shared Function IsGlobalSetting(key As String) As Boolean
    Return GlobalSettingsKeyList.Contains(key)
End Function
什么不起作用:

Using db = powerEntities.Open()
    dim userID = 1
    dim dbSettingsFound = (From setting In db.SETTINGS
                           Where setting.idUsers = If(IsGlobalSetting(setting.Name), Nothing, userID)
                           Where setting.Name.Contains(keyToMatch)) _
                        .ToDictionary(Function(x) x.Name, Function(y) y.Value)
End Using
什么是好的:

Using db = powerEntities.Open()
    dim userID = 1
    dim dbSettingsFound = (From setting In db.SETTINGS
                           Where setting.idUsers = If(GlobalSettingsKeyList.Contains(setting.Name), Nothing, userID)
                           Where setting.Name.Contains(keyToMatch)) _
                        .ToDictionary(Function(x) x.Name, Function(y) y.Value)
End Using
{“LINQ to Entities无法识别方法'Boolean IsGlobalSetting(System.String)'方法,此方法无法转换为存储表达式。”}

完成!谢谢你的回答和他的回答

所以有办法

Private Shared Function GetDefaultKey(key As String) As String
        If key.Contains("Station") Then
            Return $"default{key.Substring("Station")}" 'my String Extension
        Else
            Return $"default{key}"
        End If
End Function

Public Shared Function GetDefaultKeyAndCompareSetting(ByVal key As String) As Expression(Of Func(Of Settings, Boolean))
        key = GetDefaultKey(key)
        Return LinqExprHelper.NewExpr(Function(u As Settings) u.Name.Equals(key))
End Function
像这样使用

Shared Sub Example(key As String)
...
    Dim masterExpr = LinqExprHelper.NewExpr(Function(u As Settings, ByVal formatCompare As String) (formatCompare))
    Dim isSameAsDefKey = masterExpr.ReplacePar("formatCompare", GetDefaultKeyAndCompareSetting(key).Body)

    Dim result = (From def In db.Settings
                  Where def.idUsers Is Nothing).
                  Where(CType(isSameAsDefKey, Expression(Of Func(Of Settings, Boolean)))).FirstOrDefault
...
End Sub

…的工作原理类似于一个符咒

尝试在其周围放置一个Try/Catch块,以查看它是否引发异常{“LINQ to Entities不识别方法'System.String FormatDefaultKey(System.String)'方法,并且此方法无法转换为存储表达式。”}==其他方法中的情况相同,简单函数在LINQ to Entities查询中,您只能使用EF能够转换为本机DB查询的语法。虽然它所支持的各种语法令人印象深刻,但它并不支持任何/所有合法的.NET代码。仅仅因为它编译为有效的VB代码并不意味着EF能够解析它并将其转换为DB查询。换句话说,在本例中,它知道如何将
字典.Contains
调用转换为DB查询,但它不知道如何解析
IsGlobalSetting
方法。悲哀而有趣。。。我的函数只包含
Return GlobalSettingsKeyList.contains(key)
Right,但Where子句中的语法本质上是一个lambda表达式。它作为
表达式
传递到LINQtoEntities框架中。只有lambda可以作为表达式传递。表达式本质上是编译到语法树并作为语法树传递的,而不是完全编译的函数。因此,框架能够在运行时解析该树并分析where子句中的实际代码。因此,当它查看您的表达式时,它可以看到它包含对另一个方法的调用,但它无法解构该方法,因为它不在lambda中内联。