使用EF可以使用“或 - 或”字段,还是必须使用检查约束?

时间:2013-01-05 11:48:24

标签: sql sql-server asp.net-mvc entity-framework entity-framework-5

我正在使用MVC4,EF5和SQL Server 2012 Express LocalDB。 Customer域模型包含PhoneEmail个字段。两者都可以为null,但是,必须至少填充一个

我在客户端和服务器端使用FluentValidation确保这一点。

但是,当我需要坚持模型时,我遇到了EF5的限制。如果我同时使用了两个,那么持久化代码会失败,但如果我将它们都设为可选:

...
this.Property(q => q.Phone).IsOptional();
this.Property(q => q.Email).IsOptional();

然后这不符合我的要求。

Q1 :我如何对此进行建模 - 有一种简单的方法,还是我必须使用检查约束?这个检查约束是否正常:

ALTER TABLE dbo.[Customer]
  ADD CONSTRAINT constraintAtLeastOneContactDetailRequired
    CHECK ( ([Phone] IS NOT NULL) OR ([Email] IS NOT NULL) )
  --CHECK ( NOT(COALESCE([Phone], [Email]) IS NULL) )    <--or this?
;

Q2 :我对这两个字段都有一个UNIQUE约束,所以如果我允许它们为null并添加检查约束,那么我是否会遇到问题,因为根据定义,可能存在多个空值独特?

2 个答案:

答案 0 :(得分:1)

看起来EF不处理约束,所以我需要求助于SQL。这就是我正在做的,但可能有更好的方法:

-- enforce the either-or rule:
ALTER TABLE Customer ADD CONSTRAINT chk1 CHECK ((Phone IS NOT NULL) OR (Email IS NOT NULL));

-- columns cannot be declared as unique (because of multiple nulls), so use workaround:
CREATE UNIQUE NONCLUSTERED INDEX idx1 ON Customer(Phone) WHERE Phone IS NOT NULL;
CREATE UNIQUE NONCLUSTERED INDEX idx2 ON Contact(Email) WHERE Email IS NOT NULL;

唯一性问题是discussed here

答案 1 :(得分:0)

我认为上面的MarkG有解决方案。创建一个单独的表/实体CustomerContectDetails:

Field           Type
CustomerID      int (Foreign key link to cusotomer tables)
ContactType     int (enumerator - initially either phone or email)
ContactDetails  nvarchar(255) to hold either the email or phone number

然后一个简单的计数

if (CustomerContectDetails.Count(x => x.CustomerID == localCustomerID) > 0)
{ // positive actions}
else
{ // negative actions}

此解决方案还可以在将来扩展到其他联系人,并且可以根据联系人类型添加其他规则。并且不需要数据库约束,业务规则也在一个地方。

希望有所帮助。