Как определить взаимно-однозначное отношение "один-к-одному" в 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();
Другие вопросы по тегам