尝试学习Linq语法并且正在努力学习基于方法的vs表达式。我有8个表,允许用户关联到组和组织,并具有与组关联的表单。为了进一步解释,我将一个表单分配给一个组。该组可以直接或通过用户所属的组织分配用户。我需要一个Linq语句,它将正确地连接/联合表,以便我可以返回分配给给定用户的表单。这是基本架构:
编辑2月25日
1.注意我正在使用VS2010并编译4.0
2.从所有链接表中删除了pk id列,并在向导中启用了“包含外键列”,这清理了edmx布局(链接表现在关联设置副实体集)
3.添加了表脚本(剪掉了一些绒毛)并添加了由设计者生成的edmx
4.将我的t-sql从使用IN子句重写为EXISTS,仍然可以工作
5.仍在用LinqPad阅读和测试edmx,感叹......
CREATE TABLE [dbo].[Org](
[orgID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](100) NULL,
CONSTRAINT [PK_Org] PRIMARY KEY CLUSTERED
(
[orgID] ASC
)
CREATE TABLE [dbo].[Groups](
[groupID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Group] PRIMARY KEY CLUSTERED
(
[groupID] ASC
)
CREATE TABLE [dbo].[Form](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](100) NULL,
CONSTRAINT [PK_Form] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
CREATE TABLE [dbo].[Users](
[userID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[userID] ASC
)
###############################################################
Link tables and FKs
###############################################################
CREATE TABLE [dbo].[User_Org](
[userID] [int] NOT NULL,
[orgID] [int] NOT NULL)
ALTER TABLE [dbo].[User_Org] WITH CHECK ADD CONSTRAINT [FK_User_Org_Org] FOREIGN KEY([orgID])
REFERENCES [dbo].[Org] ([orgID])
ALTER TABLE [dbo].[User_Org] CHECK CONSTRAINT [FK_User_Org_Org]
ALTER TABLE [dbo].[User_Org] WITH CHECK ADD CONSTRAINT [FK_User_Org_Users] FOREIGN KEY([userID])
REFERENCES [dbo].[Users] ([userID])
ALTER TABLE [dbo].[User_Org] CHECK CONSTRAINT [FK_User_Org_Users]
###############################################################
CREATE TABLE [dbo].[User_Group](
[userID] [int] NOT NULL,
[groupID] [int] NOT NULL)
ALTER TABLE [dbo].[Org_Group] CHECK CONSTRAINT [FK_Org_Group_Org]
ALTER TABLE [dbo].[User_Group] WITH CHECK ADD CONSTRAINT [FK_User_Group_Group] FOREIGN KEY([groupID])
REFERENCES [dbo].[Groups] ([groupID])
ALTER TABLE [dbo].[User_Group] CHECK CONSTRAINT [FK_User_Group_Group]
ALTER TABLE [dbo].[User_Group] WITH CHECK ADD CONSTRAINT [FK_User_Group_Users] FOREIGN KEY([userID])
REFERENCES [dbo].[Users] ([userID])
ALTER TABLE [dbo].[User_Group] CHECK CONSTRAINT [FK_User_Group_Users]
###############################################################
CREATE TABLE [dbo].[Org_Group](
[orgID] [int] NOT NULL,
[groupID] [int] NOT NULL)
ALTER TABLE [dbo].[Org_Group] WITH CHECK ADD CONSTRAINT [FK_Org_Group_Group] FOREIGN KEY([groupID])
REFERENCES [dbo].[Groups] ([groupID])
ALTER TABLE [dbo].[Org_Group] CHECK CONSTRAINT [FK_Org_Group_Group]
ALTER TABLE [dbo].[Org_Group] WITH CHECK ADD CONSTRAINT [FK_Org_Group_Org] FOREIGN KEY([orgID])
REFERENCES [dbo].[Org] ([orgID])
###############################################################
CREATE TABLE [dbo].[Form_Group](
[FormID] [int] NOT NULL,
[groupID] [int] NOT NULL)
ALTER TABLE [dbo].[Form_Group] WITH CHECK ADD CONSTRAINT [FK_Form_Group_Form] FOREIGN KEY([FormID])
REFERENCES [dbo].[Form] ([ID])
ALTER TABLE [dbo].[Form_Group] CHECK CONSTRAINT [FK_Form_Group_Form]
ALTER TABLE [dbo].[Form_Group] WITH CHECK ADD CONSTRAINT [FK_Form_Group_Groups] FOREIGN KEY([groupID])
REFERENCES [dbo].[Groups] ([groupID])
ALTER TABLE [dbo].[Form_Group] CHECK CONSTRAINT [FK_Form_Group_Groups]
糟糕的T-SQL语句给了我想要的东西:
declare @userid int
set @userid = 1
select distinct(f.id)
from Form f
join Form_Group fg on f.id = fg.formid
join Groups g on fg.groupid = g.groupid
where exists
((select g1.groupid
from Groups g1
join User_Group ug on g1.groupid = ug.groupid
join Users u on ug.userid = u.userid
where u.userid = @userid
and g.groupid = g1.groupid)
union
(select g2.groupid
from Groups g2
join Org_group og on g2.groupid = og.groupid
join Org o on og.orgid = o.orgid
join User_org uo on o.orgid = uo.orgid
join Users u on uo.userid = u.userid
where u.userid = @userid
and g.groupid = g2.groupid)
)
请,谢谢!
答案 0 :(得分:1)
摆弄LinqPad,我得到了一些有用的东西!
int userID = 1;
var formIDsforUser =
(from g in Groups
from u in g.Users
where u.userID == userID
from o in g.Orgs
from u1 in o.Users
where u.userID == userID
from f in g.Form
select f.ID).Distinct();
由于概念仍然模糊,我现在感觉很厚。我认为有什么帮助是将主键转储到链接表上。有没有更好的方法来编写此查询?使用方法会是什么样子?
LinqPad的结果转换器(lambda符号)吐出:
Group.MergeAs (AppendOnly)
.SelectMany (
g => g.Users,
(g, u) =>
new
{
}
)
.Where (temp0 => (temp0.u.userID == userID))
.SelectMany (
temp0 => temp0.g.Orgs,
(temp0, o) =>
new
{
}
)
.SelectMany (
temp1 => temp1.o.Users,
(temp1, u1) =>
new
{
}
)
.Where (
temp2 =>
(temp2.<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.u.userID == userID)
)
.SelectMany (
temp2 => temp2.<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.g.Form,
(temp2, f) => f.ID
)
.Distinct ()
看起来很乱......
和LinqPad的sql结果是:
-- Region Parameters
DECLARE p__linq__0 Int = 1
DECLARE p__linq__1 Int = 1
-- EndRegion
SELECT
[Distinct1].[formID] AS [formID]
FROM ( SELECT DISTINCT
[Extent4].[formID] AS [formID]
FROM (SELECT
[User_Group].[userID] AS [userID],
[User_Group].[groupID] AS [groupID]
FROM [dbo].[User_Group] AS [User_Group]) AS [Extent1]
INNER JOIN (SELECT
[Org_Group].[orgID] AS [orgID],
[Org_Group].[groupID] AS [groupID]
FROM [dbo].[Org_Group] AS [Org_Group]) AS [Extent2]
ON [Extent1].[groupID] = [Extent2].[groupID]
INNER JOIN (SELECT
[User_Org].[userID] AS [userID],
[User_Org].[orgID] AS [orgID]
FROM [dbo].[User_Org] AS [User_Org]) AS [Extent3]
ON [Extent2].[orgID] = [Extent3].[orgID]
INNER JOIN (SELECT
[Form_Group].[formID] AS [formID],
[Form_Group].[groupID] AS [groupID]
FROM [dbo].[Form_Group] AS [Form_Group]) AS [Extent4]
ON [Extent1].[groupID] = [Extent4].[groupID]
WHERE ([Extent1].[userID] = @p__linq__0)
AND ([Extent1].[userID] = @p__linq__1)
) AS [Distinct1]
当针对db运行时,也会产生正确的结果......
答案 1 :(得分:0)
你确定你需要那么多桌子吗? 你确定所有的N:N关系吗?
我这里没有SQL Management Studio(我在我的Mac上)。但我想你可以将你的T-SQL语句简化为:
select distinct(Form.id)
from Form
inner join Form_Group on Form.formID = Form_Group.formID
inner join Group on Form_Group.groupID = Group.groupID
left outer join User_Group on Group.groupid = User_Group.groupid AND User_Group.userid = @userid
left outer join Org_Group on Group.groupid = Org_Group.groupid
inner join Org on Org_Group.orgid = Org.orgid
inner join User_Org on Org.orgid = User_Org.orgid AND User_Org.userid = @userid
这样可以更容易构建LINQ语句 这里有一些有关LINQ的有用信息和LINQ中的左外/内连接:
http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
http://odetocode.com/Blogs/scott/archive/2008/03/25/inner-outer-lets-all-join-together-with-linq.aspx