在实体框架(模型优先)中,我正在实现一个多对多(例如Composition-Anthology)关系,以及一个必须在相关集中匹配的附加关系(Composer)。
如何在 EF 中正确创建此模型?
我目前有两个坏主意:
坏主意#1
通过在 Composition 和 Anthology 组合上创建主键,同时包含 ComposerId 和本地标识,EF 正确地限制了这一点。然而,这会导致直接的问题:
- 所有与 Composition 和 Anthology 相关的表现在也具有 FK 的 ComposerId;DBA 很痛苦。
- 我不能仅根据唯一身份等使用 EF 5.0 的 EntitySet.Find()。
坏主意#2
我可以在设计器中具体化 CompositionAnthology 数据透视表,将 ComposerId 添加到其中,然后将约束直接添加到 SQL。然而这:
- 中断 EF 数据库创建/更新
- 打破实体导航/添加
注意:我的数据实际上模拟了一个不那么直观的“参与”模型,但这个比喻很有效。
编辑:我根据要求在此处发布了我的实际模型的一部分,希望我的目标可以通过不同的示意图表示来实现。(为简洁起见,我删除了 HashSet 分配。)逻辑上,Composition 表示此模型中的 Engagement,因为必须存在相关的 Engagement(具有匹配的 Account)才能存在 Endorsement。
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; }
}
我目前正在做“坏主意 #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