使用主键更新SQL Server中的外部表

时间:2010-02-20 14:49:50

标签: c# sql-server-2008 foreign-keys repository-pattern

标题可能有点误导,因为我真的不知道该怎么称呼它。 Here是我的dbml,我使用存储库模式在我的应用程序层和我的SQL层之间进行通信。如你所见,我有四张桌子。其中三个有ContactId的外键。我使用这种方法因为我需要存储一个“数组”,所以我制作了几个表。所以现在我想知道如何制作它以便我可以向联系人“添加”电子邮件地址,电话号码或地址,并通过联系人进行操作。

2 个答案:

答案 0 :(得分:2)

“显而易见”的答案是拥有一个具有addEmail,addPhone和addAddress方法的Contact类,以及数据库中匹配的存储过程。你的问题还有更多吗?

此外,虽然这不是您问题的直接部分,但您可能需要考虑规范化您的设计。处理这些类型事物的典型方法是使用一对多表。例如,您的电子邮件地址表如下所示:

EmailId (int - PK)
ContactId  (int - FK to Contact)
EmailAddress (varchar)

或者也许:

ContactId  (int - FK)
EmailNumber (tinyint? sequential 1, 2, 3, ...)
EmailAddress (varchar)

PK是ContactId和EmailNumber

无论哪种方式,每行都存储一个电子邮件地址。这样可以更轻松地添加或删除单个电子邮件,并消除当前设计中三封电子邮件的限制。它还可以更轻松地添加有关每个电子邮件地址的其他信息。例如,它是家庭或工作地址。或者,电子邮件地址是否有效。

答案 1 :(得分:0)

如果你想要一个完全标准化的设计,那么你应该有像

这样的东西
Create Table dbo.Contacts
(
    Id int not null Primary Key Clustered
    , FirstName nvarchar(25) null 
    ...
)

Create Table dbo.ContactAddresses
(
    Id int not null Primary Key Clustered
    , ContactId int not null
    , Street nvarchar(max) null
    , City nvarchar(40) null
    ...
    , Constraint FK_ContactAddresses_Contacts
        Foreign Key ( ContactId )
        References dbo.Contacts( Id )
)

Create Table dbo.ContactEmail
(
    Id int not null Primary Key Clustered
    , ContactId int not null
    , Type nvarchar(10) not null
    , Address nvarchar(255) not null
    ...
    , Constraint CK_ContactEmail_Type Check Type In('Primary','Secondary',...)
    , Constraint UK_ContactEmail_Address Unique ( ContactId, Type, Address )
    , Constraint FK_ContactEmail_Contacts
        Foreign Key ( ContactId )
        References dbo.Contacts( Id )
)

Create Table dbo.ContactPhone
(
    Id int not null Primary Key Clustered
    , ContactId int not null
    , Type nvarchar(10) not null
    , Number varchar(20) not null
    ...
    , Constraint UK_ContactPhone Unique ( ContactId, Type, Number )
    , Constraint CK_ContactPhone_Type Check Type In('Office','Fax','Home',...'Mobile')
    , Constraint FK_ContactPhone_Contacts
        Foreign Key ( ContactId )
        References dbo.Contacts( Id )
)

如果您想要更受控制的电子邮件或电话类型列表,可以添加父表和外键来存储它们。这种设计缺少的是防止地址欺骗。用户是否需要输入完整地址?此设计允许无限制的电子邮件,电话号码和地址。但是,这可能对你所需要的东西来说太过分了。

如果您正在设计一个完整的联系人管理器来替换像Outlook这样的东西,那么上述设计将是可行的方法。但是,大多数捕获某些联系人数据的系统并不是完整的联系人管理员。如果是这种情况,那么您应该对要捕获的数据量进行一些合理的保留。例如,您是否真的允许用户为单个联系人输入八个电话号码? 99%的联系人只有两到三个电话号码可能更为现实。在联系人中包含一个nvarchar(max)注释列,供想要捕获数百个电话号码和电子邮件地址的人使用。如果是这种情况,那么您可以对设计进行非规范化处理:

Create Table dbo.Contacts
(
    Id int not null Primary Key Clustered
    , FirstName nvarchar(25) null 
    ...
    , PrimaryEmailAddress nvarchar(255) null
    , SecondaryEmailAddress nvarchar(255) null
    , OfficePhone nvarchar(25) null
    , MobilePhone nvarchar(25) null
    , FaxPhone nvarchar(25) null
    , Note nvarchar(max) null
    ...
    , Constraint UK_Contacts Unique ( FirstName.... )
)

此时唯一的问题是地址。在我做到这一点之前,如果管理层说“嘿,我们想再存储五个电话号码”,你应该告诉他们系统不是Outlook的替代品。如果用户想要存储的电话号码多于您提供的电话号码,请将其放入“备注”列。使用地址,您需要知道需要存储多少个地址。如果它超过两个(甚至一个),我的建议是仍然把它放在一个单独的表中。

灵活性与复杂性相关1:1。管理无限数量的电子邮件地址,电话号码和地址更加灵活,但在UI中添加了更多工作。大多数联系人捕获设计并不需要捕获给定联系人的数十个电子邮件地址,因此完全标准化的设计只是添加了超出必要的工作量。