2009-01-31 13 views
15

Mam ograniczenie klucza obcego między tabelami Sesje i użytkownicy. W szczególności Sessions.UID = Users.ID. Czasami chcę, aby Sesje.UID były puste. Czy to może być dozwolone? Za każdym razem, gdy próbuję to zrobić, otrzymuję naruszenie ograniczeń FK.SQL Server 2005: zerowalny klucz obcy

W szczególności wstawiam wiersz do Sesji przez LINQ. Ustawiłem Session.User = null; i otrzymuję ten błąd:

An attempt was made to remove a relationship between a User and a Session. However, one of the relationship's foreign keys (Session.UID) cannot be set to null.

Jednak, kiedy usunąć wiersz null właściwość użytkownika, otrzymuję ten błąd na moim SubmitChanges line:

Value cannot be null. 
Parameter name: cons

Żaden z moich tabelach pole zwanych wad ", ani w moim pliku 5,500-wierszowym DataContext.designer.cs, ani nie jest w QuickWatch dla żadnego z powiązanych obiektów, więc nie mam pojęcia, jakie są" minusy ".

W bazie danych Session.UID jest polem z wartościami zerowymi, a User.ID jest int non-null. Chcę nagrywać sesje, które mogą mieć lub nie mieć UID, i wolałbym to zrobić bez wyłączania ograniczenia dla tej relacji FK. Czy jest jakiś sposób na zrobienie tego?

Odpowiedz

27

Wydaje mi się, że pamiętam tworzenie nullable FK przed, więc wziąłem szybki test. Jak widać poniżej, jest to zdecydowanie wykonalne (testowane na MSSQL 2005).

Skryptuj odpowiednie części swoich tabel i wiązań i opublikuj je, abyśmy mogli dalej rozwiązywać problemy.

CREATE DATABASE [NullableFKTest] 
GO 
USE [NullableFKTest] 
GO 
CREATE TABLE OneTable 
(
    OneId [int] NOT NULL, 
    CONSTRAINT [PK_OneTable] PRIMARY KEY CLUSTERED 
    (
     [OneId] ASC 
    ) 
) 
CREATE TABLE ManyTable (ManyId [int] IDENTITY(1,1) NOT NULL, OneId [int] NULL) 
GO 
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ManyTable_OneTable]') AND parent_object_id = OBJECT_ID(N'[dbo].[ManyTable]')) 
ALTER TABLE [dbo].[ManyTable] WITH CHECK ADD CONSTRAINT [FK_ManyTable_OneTable] FOREIGN KEY([OneId]) 
    REFERENCES [dbo].[OneTable] ([OneId]) 
GO 

--let's get a value in here 
insert into OneTable(OneId) values(1) 
select* from OneTable 

--let's try creating a valid relationship to the FK table OneTable 
insert into ManyTable(OneId) values (1) --fine 
--now, let's try NULL 
insert into ManyTable(OneId) values (NULL) --also fine 
--how about a non-existent OneTable entry? 
insert into ManyTable(OneId) values (5) --BOOM! - FK violation 

select* from ManyTable 
--1, 1 
--2, NULL 

--cleanup 
ALTER TABLE ManyTable DROP CONSTRAINT FK_ManyTable_OneTable 
GO 
drop TABLE OneTable 
GO 
drop TABLE ManyTable 
GO 
USE [Master] 
GO 
DROP DATABASE NullableFKTest 
+7

Prawy ad. +1 Definicja klucza obcego polega na tym, że jest to wartość w jednej tabeli, która musi być zgodna z wartością klucza podstawowego w innej tabeli lub mieć wartość null. – Alan

+1

Logicznie rzecz biorąc, ma to sens, prawda? Przeczytałem to tak: JEŚLI próbuję odwołać się do rekordu w innej tabeli, upewnij się, że odniesienie jest prawidłowe. Jeśli nie (NULL), kogo to obchodzi. –