1

Entity Framework (モデル優先) では、関連セット内で一致する必要がある追加の関係 (Composer) を使用して、多対多 (構成-アンソロジーなど) の関係を実装しています。

ここに画像の説明を入力

このモデルを EF で正しく作成するにはどうすればよいですか?

私は現在、2つの悪い考えを持っています:

悪い考え #1

ComposerId とローカル ID の両方を含むコンポジションおよびアンソロジー コンポジットの主キーを作成することにより、EF はこれを正しく制約します。ただし、これはすぐに問題を引き起こします。

  • コンポジションとアンソロジーに関連するすべてのテーブルには、FK の ComposerId も含まれるようになりました。DBAにとっては苦痛です。
  • 一意の ID などに基づいて EF 5.0 の EntitySet.Find() を使用することはできません。

悪い考え #2

デザイナで CompositionAnthology ピボット テーブルを具体化し、それに ComposerId を追加して、SQL に直接制約を追加することができました。ただし、これ:

  • EF データベースの作成/更新を中断します
  • エンティティのナビゲーション/追加を中断します

注: 私のデータは、実際にははるかに直感的ではない「エンゲージメント」モデルをモデル化していますが、この比喩は非常によく当てはまります。


編集: 別の図式表現で目標を達成できる可能性があるため、要求に応じて実際のモデルの一部をここに投稿しています。(簡潔にするために HashSet の割り当てを削除しました。) 論理的には、構成はこのモデルのエンゲージメントを表します。これは、承認が存在するためには、(一致するアカウントを持つ) 関連するエンゲージメントが存在する必要があるためです。

public partial class Account
{
    public int Id { get; set; }
    public string PrimaryEmail { get; set; }

    public virtual ICollection<Endorsement> EndorsementsGiven { get; set; }
    public virtual ICollection<Endorsement> EndorsementsReceived { get; set; }
    public virtual ICollection<Engagement> Engagements { get; set; }
    public virtual ICollection<EngagementEndorsement> EngagementEndorsements { get; set; }
}

public partial class EngagementEndorsement
{
    public int Endorsement_Id { get; set; }
    public int Engagement_Id { get; set; }
    public int Account_Id { get; set; }

    public virtual Endorsement Endorsement { get; set; }
    public virtual Engagement Engagement { get; set; }
    public virtual Account Account { get; set; }
}

public partial class Engagement
{
    public int Id { get; set; }
    public System.DateTime Start { get; set; }
    public System.DateTime End { get; set; }
    public string JobFunction { get; set; }

    public virtual Account Account { get; set; }
    public virtual ICollection<EngagementEndorsement> EngagementEndorsements { get; set; }
}

public partial class Endorsement
{
    public int Id { get; set; }
    public EndorsementStatus Status { get; set; }
    public EndorserRole EndorserRole { get; set; }
    public string Note { get; set; }

    public virtual Account Endorsee { get; set; }
    public virtual Account Endorser { get; set; }
    public virtual ICollection<EngagementEndorsement> EngagementEndorsements { get; set; }
}

現在、「Bad Idea #2」(上記参照) を行っています。データベースが作成された後、追加の関係/制約を適用します。

-- --------------------------------------------------
-- Ensure Engagement-to-Endorsement AccountId match
-- --------------------------------------------------

ALTER TABLE [dbo].[Engagements]
ADD CONSTRAINT [UK_EngagementIdAccountId]
    UNIQUE NONCLUSTERED
        ([Id], [Account_Id])
    WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

ALTER TABLE [dbo].[EngagementEndorsements]
ADD CONSTRAINT [FK_EngagementIdAccountId]
    FOREIGN KEY ([Engagement_Id], [Account_Id])
    REFERENCES [dbo].[Engagements]
        ([Id], [Account_Id])
    ON DELETE NO ACTION ON UPDATE NO ACTION;

ALTER TABLE [dbo].[Endorsements]
ADD CONSTRAINT [UK_EndorsementIdAccountId]
    UNIQUE NONCLUSTERED
        ([Id], [Endorsee_Id])
    WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

ALTER TABLE [dbo].[EngagementEndorsements]
ADD CONSTRAINT [FK_EndorsementIdAccountId]
    FOREIGN KEY ([Endorsement_Id], [Account_Id])
    REFERENCES [dbo].[Endorsements]
        ([Id], [Endorsee_Id])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
GO
4

1 に答える 1

0

最終的に、2 つの関連する質問での優れたデータ スキーマ フィードバック (および EF フィードバックの欠如) に基づいて、上記の「悪い考え #2」に示されているように進めました。

私はこれを使用してきましたが、現在のすべてのニーズを満たしています。

実装の他のビットの詳細については、これらを参照してください。

于 2013-05-08T13:29:26.380 に答える