1

MVC4、EF5、および SQL Server 2012 Express LocalDB を使用しています。Customerドメイン モデルにはとPhoneフィールドEmailがあります。どちらも null にすることができますが、少なくとも 1 つが入力されている必要があります

クライアント側とサーバー側の両方で 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 にすることを許可してチェック制約を追加すると、定義上一意ではない複数の null が存在する可能性があるため、問題が発生しますか?

4

2 に答える 2

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;

一意性の問題については、ここで説明します

于 2013-01-05T17:55:18.480 に答える
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}

このソリューションは、将来的に追加の連絡先に拡張することもでき、連絡先の種類に基づいて追加のルールを追加することもできます。また、データベースの制約は不要で、ビジネス ルールは 1 か所にとどまります。

それが役立つことを願っています。

于 2013-01-05T13:05:22.897 に答える