如何在 SQL Server 和 LINQ-to-SQL 中定义单侧可选一对一关系?
我正在尝试在 User 表和 UserInfo 表之间创建一侧可选的一对一关系。规范是一个 UserInfo 必须恰好有一个 User,而一个 User 可以有一个或零个 UserInfo。另外,我们要求外键存在于 UserInfo 表中,以便 User 表的列不被修改。我们希望使用 C# LINQ-to-SQL 中的关系,例如 user.UserInfo.Email = "[email protected]",
userInfo.User`等。
表的 T-SQL 以及从 UserInfos 到 Users 的外键是(大致):
CREATE TABLE [dbo].[Users](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[Username] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ( [UserId] ASC ),
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[UserInfos](
[UserInfoId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[Email] [varchar](250) NOT NULL,
CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED ( [UserInfoId] ASC ),
CONSTRAINT [UQ_UserId] UNIQUE NONCLUSTERED ( [UserId] ASC )
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[UserInfos] WITH CHECK
ADD CONSTRAINT [FK_UserInfos.UserID_Users.UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[Users] ([UserId])
GO
ALTER TABLE [dbo].[UserInfos] CHECK CONSTRAINT [FK_UserInfos.UserID_Users.UserId]
GO
问题是,如果我定义从 Users.UserId (主键)到 UserInfos.UserId (即,我了解,定义非可选一对一关系的正确方法)然后执行 LINQ-to-SQL 代码 user.UserInfo = null
还会设置 <代码>user.UserId 到default(int)
。
以下是我用来定义 Users
和 UserInfos
之间的外键的 T-SQL:
ALTER TABLE [dbo].[Users] WITH CHECK
ADD CONSTRAINT [FK_Users.UserId_UserInfos.UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[UserInfos] ([UserId])
GO
ALTER TABLE [dbo].[Users] CHECK CONSTRAINT [FK_Users.UserId_UserInfos.UserId]
GO
如果我不定义此外键,则不会得到 LINQ-to-SQL User
上的属性允许我访问 UserInfo
。如何在表 Users
和 UserInfos
之间建立可通过 LINQ-to-SQL 遍历的关系,同时允许该关系在 <代码>用户端?谢谢。
I am trying to create a one-to-one relationship that is optional on one side between a User table and a UserInfo table. The specifications are that a UserInfo must have exactly one User, while a User can have one or zero UserInfos. Also we require that the foreign key exist in the UserInfo table so that the columns of the User table are not modified. We would like to use the relationship in C# LINQ-to-SQL, e.g., user.UserInfo.Email = "[email protected]",
userInfo.User`, etc.
The T-SQL for the tables and the foreign key from UserInfos to Users is (roughly):
CREATE TABLE [dbo].[Users](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[Username] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ( [UserId] ASC ),
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[UserInfos](
[UserInfoId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[Email] [varchar](250) NOT NULL,
CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED ( [UserInfoId] ASC ),
CONSTRAINT [UQ_UserId] UNIQUE NONCLUSTERED ( [UserId] ASC )
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[UserInfos] WITH CHECK
ADD CONSTRAINT [FK_UserInfos.UserID_Users.UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[Users] ([UserId])
GO
ALTER TABLE [dbo].[UserInfos] CHECK CONSTRAINT [FK_UserInfos.UserID_Users.UserId]
GO
The problem is that if I define a foreign key from Users.UserId (the primary key) to UserInfos.UserId (which is, I understand, the correct way to define a non-optional one-to-one relationship) then performing the LINQ-to-SQL code user.UserInfo = null
also sets the user.UserId
to default(int)
.
Here is the T-SQL I use to define the foreign key between Users
and UserInfos
:
ALTER TABLE [dbo].[Users] WITH CHECK
ADD CONSTRAINT [FK_Users.UserId_UserInfos.UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[UserInfos] ([UserId])
GO
ALTER TABLE [dbo].[Users] CHECK CONSTRAINT [FK_Users.UserId_UserInfos.UserId]
GO
If I do not define this foreign key, then I get no LINQ-to-SQL property on a User
allowing me to access the UserInfo
. How can I have a relationship between the table Users
and UserInfos
that is traversable with LINQ-to-SQL, while at the same time allowing this relationship to be null from the User
side? Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你可以做到这一点,但你的做法是错误的。
当你调用
异常时指出
LINQ-to-SQL 认为您正在尝试删除两项之间的关系;并且以一种间接的方式你是。但例外只是重申您自己所说的 -
UserInfo
必须有一个User
。您取消了这两个对象的链接,但没有删除UserInfo
- 您在上下文中留下了一个孤立的UserInfo
,它无法持久保存到数据库中(由于外键约束)。答案是什么呢?删除
用户信息
。You can do this but you're approaching it from the wrong side.
When you call
the exception states that
LINQ-to-SQL thinks you are trying to remove the relationship between the two items; and in an indirect way you are. But the exception is just a reiteration of what you've stated yourself - a
UserInfo
must have aUser
. You're unlinking the two objects but you aren't removing theUserInfo
- you're leaving an orphanedUserInfo
in your context which cannot be persisted to the database (due to the foreign key constraint).The answer? Delete the
UserInfo
.