Как определить взаимно-однозначное отношение «один-к-одному» в SQL Server и LINQ-to-SQL? - PullRequest
3 голосов
/ 06 сентября 2011

Я пытаюсь создать взаимно-однозначное отношение, которое является необязательным с одной стороны между таблицей User и таблицей UserInfo. Спецификации состоят в том, что UserInfo должен иметь ровно одного пользователя, в то время как пользователь может иметь один или ноль UserInfos. Также мы требуем, чтобы внешний ключ существовал в таблице 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 (который, как я понимаю, является правильным способом определения необязательного one- отношение «один к одному», затем выполнение кода LINQ-to-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 Ответ

1 голос
/ 04 октября 2011

Вы можете сделать это, но подходите к нему не с той стороны.

Когда вы звоните

user.UserInfo = null;

, исключение говорит о том, что

Anбыла предпринята попытка удалить связь между пользователем и пользовательской информацией.Однако один из внешних ключей отношения (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();
...