vb.net - Entity Framework 多对多使用 VB.Net Lambda

标签 vb.net linq entity-framework

我在 Visual Studio 2010 Beta 2(.NET framework 4.0 Beta 2)中使用 Entity Framework 。我从我的数据库创建了一个 Entity Framework .edmx 模型,并且我有一些多对多关系。

我的数据库架构的一个简单示例是

  • 角色(ID、名称、事件)
  • 成员(ID、出生日期、创建日期)
  • RoleMembership(RoleID, MemberID)

  • 我现在正在编写自定义角色提供程序 (Inheriting System.Configuration.Provider.RoleProvider) 并开始编写 IsUserInRole(username, roleName) 的实现。

    我编写的 LINQ-to-Entity 查询,在 SQL-Profiled 时,都生成了 CROSS JOIN 语句,而我想要的是它们到 INNER JOIN。
            Dim query = From m In dc.Members
                        From r In dc.Roles
                        Where m.ID = 100 And r.Name = "Member"
                        Select m
    

    我的问题几乎完全在这里描述:
    Entity framework and many to many queries unusable?

    我确信那里提供的解决方案效果很好,但是虽然我在 uni 学习了 Java 并且我基本上可以理解 C#,但我无法理解提供的这种 Lambda 语法,我需要在 VB 中获得一个类似的示例。我已经在网上浏览了半天的大部分时间,但我并没有接近我的答案。

    所以请有人建议我如何在 VB 中构造一个 LINQ 语句,它可以在 SQL 中执行此等效操作:
    SELECT rm.RoleID
    FROM RoleMembership rm 
      INNER JOIN Roles r ON r.ID = rm.RoleID
      INNER JOIN Members m ON m.ID = rm.MemberID
    WHERE r.Name = 'Member' AND m.ID = 101
    

    我将使用此查询来查看成员 101 是否在角色 3 中。
    (我很感激我可能不需要在 SQL 中加入成员表,但我想在 LINQ 中我需要引入成员对象?)

    更新:

    我通过使用多种方法更接近:
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim count As Integer
    
        Using dc As New CBLModel.CBLEntities
    
            Dim persons = dc.Members.Where(AddressOf myTest)
    
            count = persons.Count
    
        End Using
    
        System.Diagnostics.Debugger.Break()
    End Sub
    
    Function myTest(ByVal m As Member) As Boolean
        Return m.ID = "100" AndAlso m.Roles.Select(AddressOf myRoleTest).Count > 0
    End Function
    
    Function myRoleTest(ByVal r As Role) As Boolean
        Return r.Name = "Member"
    End Function
    

    SQL Profiler 显示:

    SQL:批量启动
    SELECT 
    [Extent1].[ID] AS [ID], 
    ... (all columns from Members snipped for brevity) ...
    FROM [dbo].[Members] AS [Extent1]
    

    RPC:已完成
    exec sp_executesql N'SELECT 
    [Extent2].[ID] AS [ID], 
    [Extent2].[Name] AS [Name], 
    [Extent2].[Active] AS [Active]
    FROM  [dbo].[RoleMembership] AS [Extent1]
    INNER JOIN [dbo].[Roles] AS [Extent2] ON [Extent1].[RoleID] = [Extent2].[ID]
    WHERE [Extent1].[MemberID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=100
    

    SQL:批量完成
    SELECT 
    [Extent1].[ID] AS [ID], 
    ... (all columns from Members snipped for brevity) ...
    FROM [dbo].[Members] AS [Extent1]
    

    我不确定为什么它在内部连接语句中使用 sp_execsql 以及为什么它仍然运行选择来选择所有成员。

    谢谢。

    更新 2

    我通过将上述“多种方法”转换为 lambda 表达式然后全部转换为一个查询来编写它,如下所示:
        Dim allIDs As String = String.Empty
    
        Using dc As New CBLModel.CBLEntities
    
            For Each retM In dc.Members.Where(Function(m As Member) m.ID = 100 AndAlso m.Roles.Select(Function(r As Role) r.Name = "Doctor").Count > 0)
                allIDs &= retM.ID.ToString & ";"
            Next
    
        End Using
    

    但它似乎不起作用:“医生”不是一个存在的角色,我只是将它放在那里进行测试,但“allIDs”仍然设置为“100;”

    这次 SQL Profiler 中的 SQL 是这样的:
    SELECT 
    [Project1].*
    FROM ( SELECT 
        [Extent1].*, 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[RoleMembership] AS [Extent2]
            WHERE [Extent1].[ID] = [Extent2].[MemberID]) AS [C1]
        FROM [dbo].[Members] AS [Extent1]
    )  AS [Project1]
    WHERE (100 = [Project1].[ID]) AND ([Project1].[C1] > 0)
    

    为简洁起见,我将成员表中所有列的列表变成了 *

    如您所见,它只是忽略了“角色”查询。

    最佳答案

    这就是我使用 Lambda 表达式解决它的方法:

        Public Overrides Function IsUserInRole(ByVal username As String, ByVal roleName As String) As Boolean
            Dim retVal As Boolean
    
            Using db As New CBLEntities
                Dim theRole = db.Roles.Where(Function(x) x.Name = roleName)
                retVal = theRole.Any(Function(r As Role) r.Members.Where(Function(m As Member) m.ID = username).Any())
            End Using
    
            Return retVal
        End Function
    

    关于vb.net - Entity Framework 多对多使用 VB.Net Lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2243462/

    相关文章:

    C# LINQ to Entities-对象和对象集合交集的属性

    c# - Entity Framework /LINQ : Left join defaultifempty fails

    vb.net - 单击时动态更改笔的颜色和绘画

    vb.net - VB 2010 : How to copy all subfolders of a folder in an other folder?

    c# - 如何执行 Entity Framework 跟踪sql

    .net - 在 LINQ 中如何找到连接 2 个表的不同项目?

    linq - 使用 Entity Framework 连接查询

    .net - 忽略 .net 中窗口字体大小的增加

    javascript - 隐藏输入 "empty string"与 "null"Javascript、VB

    c# - vb.net和c#的GroupBy区别