Как определить взаимно-однозначное отношение "один-к-одному" в SQL Server и LINQ-to-SQL?
Я пытаюсь создать взаимно-однозначное отношение, которое является необязательным с одной стороны между таблицей User и таблицей UserInfo. Спецификации состоят в том, что UserInfo должен иметь ровно одного пользователя, в то время как пользователь может иметь один или ноль пользовательских сведений. Также мы требуем, чтобы внешний ключ существовал в таблице UserInfo, чтобы столбцы таблицы User не изменялись. Мы хотели бы использовать отношения в C# LINQ-to-SQL, например, user.UserInfo.Email = "test@test.com",
userInfo.User` и др.
T-SQL для таблиц и внешний ключ от UserInfos для пользователей (примерно):
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. код в SQL user.UserInfo = null
также устанавливает user.UserId
в default(int)
,
Вот T-SQL, который я использую для определения внешнего ключа между Users
а также 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
Если я не определю этот внешний ключ, я не получу свойство LINQ-to-SQL на User
позволяя мне получить доступ к UserInfo
, Как я могу иметь отношения между столом Users
а также UserInfos
это можно обойти с помощью LINQ-to-SQL, в то же время позволяя этому отношению быть нулевым из User
боковая сторона? Спасибо.
1 ответ
Вы можете сделать это, но вы подходите к этому не с той стороны.
Когда вы звоните
user.UserInfo = null;
исключение гласит, что
Была предпринята попытка удалить связь между пользователем и пользовательской информацией. Однако один из внешних ключей отношения (UserInfo.UserId) не может быть установлен в нуль.
LINQ-to-SQL думает, что вы пытаетесь удалить связь между этими двумя элементами; и косвенным образом вы есть. Но исключением является лишь повторение того, что вы сами заявили - UserInfo
должен иметь User
, Вы отменяете связь двух объектов, но не удаляете UserInfo
- ты покидаешь сироту UserInfo
в вашем контексте, который не может быть сохранен в базе данных (из-за ограничения внешнего ключа).
Ответ? Удалить UserInfo
,
var user = context.Users.First();
var userinfo = user.UserInfos;
user.UserInfos = null;
context.UserInfos.DeleteOnSubmit(userinfo);
context.SubmitChanges();
// or, even simpler:
var user = context.Users.First();
context.UserInfos.DeleteOnSubmit(user.UserInfos);
context.SubmitChanges();