Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用VB.Net Lambda的实体框架多对多_Vb.net_Linq_Entity Framework - Fatal编程技术网

使用VB.Net Lambda的实体框架多对多

使用VB.Net Lambda的实体框架多对多,vb.net,linq,entity-framework,Vb.net,Linq,Entity Framework,我正在Visual Studio 2010 Beta 2.NET Framework 4.0 Beta 2中使用实体框架。我已经从我的数据库中创建了一个entity framework.edmx模型,并且我有一些多对多关系 我的数据库模式的一个简单示例是 角色ID、名称、活动 成员ID、DateOfBirth、DateCreated RoleMembershipRoleID,成员ID 我现在正在编写继承System.Configuration.provider.RoleProvider的自定义角

我正在Visual Studio 2010 Beta 2.NET Framework 4.0 Beta 2中使用实体框架。我已经从我的数据库中创建了一个entity framework.edmx模型,并且我有一些多对多关系

我的数据库模式的一个简单示例是

角色ID、名称、活动 成员ID、DateOfBirth、DateCreated RoleMembershipRoleID,成员ID 我现在正在编写继承System.Configuration.provider.RoleProvider的自定义角色提供程序,并开始编写IsUserInRoleusername、roleName的实现

我编写的LINQtoEntity查询在分析SQL时都会生成交叉连接语句,而我希望它们内部连接

        Dim query = From m In dc.Members
                    From r In dc.Roles
                    Where m.ID = 100 And r.Name = "Member"
                    Select m
我的问题几乎完全描述在这里:

我确信这里提供的解决方案工作得很好,但是当我在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中我可能不需要连接到Members表,但我想在LINQ中我需要引入Member对象

更新:

通过使用多种方法,我更接近:

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事件探查器显示了以下内容:

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,为什么它仍然运行select来选择所有成员

谢谢

更新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
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)
但它似乎不起作用:医生并不是一个存在的角色,我只是把它放在那里用于测试目的,但AllID仍然设置为100

这次SQL探查器中的SQL如下所示:

    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
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)
为了简洁起见,我将Members表中所有列的列表转换为*


正如您所看到的,它只是忽略了角色查询。

如果在架构中未使用关联映射或外键,则可以使用此sintax:

Dim query = From rm As RoleMembership _
            In RoleMemberships _
            Join m As Member In Members On m.ID Equals rm.MemberID _
            Join r As Role In Roles On r.ID Equals rm.RoleID _
            Where r.Name = "Member" _
                And m.ID = 100 _
            Select rm
如果您使用的是关联,则其方式如下:

Dim query2 = From r As Role _
             In Roles _
             Where r.Name = "Member" _
                 And r.Members.Any(Function(m As Member) m.ID = 100) _
             Select r

下面是我如何使用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

我已经标记为答案,因为这确实有效,但我将添加我自己的答案,以展示我如何在Lambda表达式中实现它。谢谢,您还可以使用ESQL实体SQL来解决这个问题,以获得更动态的解决方案。请参阅msdn.microsoft.com/en-us/library/bb387118.aspx