对于Entityframework 3.使用Database First方法时,如何避免桥表

时间:2013-07-10 12:32:18

标签: .net entity-framework

业务案例是:发送带有合同列表的消息,消息应存储在数据库中。合同可以属于多个消息,报告可以显示与某个合同相关的消息,但这与我的代码无关。我的代码只需要一次存储一条消息。

我有3个表Message,Contract和ContractMessage。我首先使用模式(数据库优先)方法,创建ContractMessage实体。我不需要那个实体,我只需要一个List<类型的属性。合同>内部消息。目前我甚至没有兴趣拥有一个List<消息>在合同内。

我是EF的新手,我听说EF 1充满了麻烦。我应该保留桥牌表吗?可以删除桥接表并将其转换为属性以及如何从模型中删除这些桥接表以及如何修复映射。

2 个答案:

答案 0 :(得分:0)

如果您的桥牌表没有任何有趣的列(只有MessageIdContractId除外),那么它在您的模型中就没用了。

你只想要Message.Contracts导航属性(你不需要Contract.Messages)。

使用Model First方法,只需拖动&将2个实体放到设计器中并配置多对多关联

enter image description here

由于您不需要Contract.Messages,只需单击导航属性并将其删除即可。

从模型创建数据库模式时,Entity Framework将为您生成桥接表:

-- --------------------------------------------------
-- Creating all tables
-- --------------------------------------------------

-- Creating table 'Messages'
CREATE TABLE [dbo].[Messages] (
    [Id] int IDENTITY(1,1) NOT NULL,
    [Value] nvarchar(max)  NOT NULL
);
GO

-- Creating table 'Contracts'
CREATE TABLE [dbo].[Contracts] (
    [Id] int IDENTITY(1,1) NOT NULL,
    [Value] nvarchar(max)  NOT NULL
);
GO

-- Creating table 'MessageContract'
CREATE TABLE [dbo].[MessageContract] (
    [Messages_Id] int  NOT NULL,
    [Contracts_Id] int  NOT NULL
);
GO

-- --------------------------------------------------
-- Creating all PRIMARY KEY constraints
-- --------------------------------------------------

-- Creating primary key on [Id] in table 'Messages'
ALTER TABLE [dbo].[Messages]
ADD CONSTRAINT [PK_Messages]
    PRIMARY KEY CLUSTERED ([Id] ASC);
GO

-- Creating primary key on [Id] in table 'Contracts'
ALTER TABLE [dbo].[Contracts]
ADD CONSTRAINT [PK_Contracts]
    PRIMARY KEY CLUSTERED ([Id] ASC);
GO

-- Creating primary key on [Messages_Id], [Contracts_Id] in table 'MessageContract'
ALTER TABLE [dbo].[MessageContract]
ADD CONSTRAINT [PK_MessageContract]
    PRIMARY KEY NONCLUSTERED ([Messages_Id], [Contracts_Id] ASC);
GO

-- --------------------------------------------------
-- Creating all FOREIGN KEY constraints
-- --------------------------------------------------

-- Creating foreign key on [Messages_Id] in table 'MessageContract'
ALTER TABLE [dbo].[MessageContract]
ADD CONSTRAINT [FK_MessageContract_Message]
    FOREIGN KEY ([Messages_Id])
    REFERENCES [dbo].[Messages]
        ([Id])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
GO

-- Creating foreign key on [Contracts_Id] in table 'MessageContract'
ALTER TABLE [dbo].[MessageContract]
ADD CONSTRAINT [FK_MessageContract_Contract]
    FOREIGN KEY ([Contracts_Id])
    REFERENCES [dbo].[Contracts]
        ([Id])
    ON DELETE NO ACTION ON UPDATE NO ACTION;

-- Creating non-clustered index for FOREIGN KEY 'FK_MessageContract_Contract'
CREATE INDEX [IX_FK_MessageContract_Contract]
ON [dbo].[MessageContract]
    ([Contracts_Id]);
GO

答案 1 :(得分:0)

如果实体框架将桥接表创建为具有数据库优先方法的实体,则通常意味着桥接表没有将所需的模式识别为多对多关系的桥接表 - 这是:

  • 桥接表必须包含完全 (number of primary key columns in left entity) + (number of primary key columns in right entity)列。例如:如果左右实体表(ContractMessage)没有复合键,只有一个主键列,则桥表中的列数必须为完全 2

  • 桥接表中的所有列必须形成一个复合主键。

  • 在左实体表的主键和桥表中的第一列之间,必须在数据库中定义外键约束,即第一列桥表中的(s)是左实体表的外键。

  • 这同样适用于桥接表中的右实体表和最后一列。

  • 我不确定这一点(尤其不适用于EF 1),但可能要求上述两个外键关系必须启用级联删除

如果满足这些规则,则不应将桥接表创建为实体。这适用于所有版本的实体框架,包括EF 1。

如果不满足其中一个要求,EF将不会检测多对多关系,并将桥接表创建为实体。

这可能取决于哪些要求未得到满足的详细信息,但通常我会说您无法更改EF模型以定义工作的多对多关系,而无需相应地更改数据库架构。例如,如果桥表中有一个单独的主键列(除了左右实体的FK之外),您可能必须将桥实体保留在模型中。

最佳解决方案是调整数据库架构,使其符合上述规则 - 如果您可以更改它。