【问题标题】:EF code-first many-to-many with additional data带有附加数据的 EF 代码优先多对多
【发布时间】:2012-04-17 21:06:15
【问题描述】:

我有这些表:

CREATE TABLE [EDR_SECURITY].[Person](
    [ixPerson] [bigint] IDENTITY(1,1) NOT NULL,
    [sName] [nvarchar](200) NOT NULL,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]



CREATE TABLE [EDR_SECURITY].[SecurityGroup](
    [ixSecurityGroup] [bigint] IDENTITY(1,1) NOT NULL,
    [sName] [nvarchar](200) NOT NULL,
    [sDescription] [nvarchar](400) NULL,
) ON [PRIMARY]


CREATE TABLE [EDR_SECURITY].[PersonSecurityGroupDefinition](
    [ixPerson] [bigint] NOT NULL,
    [ixSecurityGroup] [bigint] NOT NULL,
    [fPrivilege] [bigint] NOT NULL,
 CONSTRAINT [PK_PersonSecurityGroupDefinition] PRIMARY KEY CLUSTERED 
(
    [ixPerson] ASC,
    [ixSecurityGroup] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

如何在 EF 代码优先中创建 PersonSecurity Group 之间的关系?

谢谢。

【问题讨论】:

  • 如果您发布代码、XML 或数据示例,在文本编辑器中突出显示这些行,然后单击编辑器上的“代码示例”按钮 ({ })工具栏以很好地格式化和语法突出显示它!

标签: sql-server entity-framework ef-code-first


【解决方案1】:

如果我从原始 SQL 中完全理解...

编辑:正如在您的具体情况中所建议的那样,我认为这至少非常接近......

public class Person
{
    public int PersonID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<PersonSecurityGroupDefinition> 
        PersonSecurityGroups { get; set; }
}
public class SecurityGroup
{
    public int SecurityGroupID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual ICollection<PersonSecurityGroupDefinition> 
        PersonSecurityGroups { get; set; }
}
public class PersonSecurityGroupDefinition
{
    public int PersonID { get; set; }
    public int SecurityGroupID { get; set; }
    public int Privilege { get; set; }
    // don't use virtual here as these are PK-s
    public Person Person { get; set; }
    public SecurityGroup SecurityGroup { get; set; }
}

...在OnModelCreating 中(覆盖您的DbContext...

modelBuilder.Entity<PersonSecurityGroupDefinition>()
    .HasKey(i => new { i.PersonID, i.SecurityGroupID });

modelBuilder.Entity<PersonSecurityGroupDefinition>()
    .HasRequired(i => i.Person)
    .WithMany(u => u.PersonSecurityGroups)
    .HasForeignKey(i => i.PersonID)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<PersonSecurityGroupDefinition>()
    .HasRequired(i => i.SecurityGroup)
    .WithMany(d => d.PersonSecurityGroups)
    .HasForeignKey(i => i.SecurityGroupID)
    .WillCascadeOnDelete(false);

...希望就是这样。

【讨论】:

  • 我也是,仔细看 - 这是索引表,它是多对多的 - 您只需将 User w/Person、Role 替换为 SecurityGroup 并且您的 PersonSecurityGroupDefinition 是 UserRole。
  • 您真的可以多花一点时间用问题中的名称替换类和属性名称,并展示其他两个实体的外观。你知道完整的答案,只是感觉有点懒惰,复制并粘贴另一个模型到答案中并说“这里,这非常相似”。
  • +1:很好的答案 :) 我不明白为什么导航。连接实体中的属性不应该是virtual,它们代表正常的外键关系。 FK同时是PK的一部分在imo中并不重要。我还将删除WillCascadeOnDelete(false),因为连接表通常具有级联删除。不会出现“多级联删除路径”异常,因为两个级联删除来自不同的表。
  • @Slauma 对编辑提出的观点 :) - 已编辑 - 我只是没有时间,我觉得一个好的指针会让人们更多地“参与”。尽管如此,你是对的,所以它似乎是一种主要的回答方式(彻底的答案)。
  • @Slauma 如果是 PK-s(或相应的导航属性)的 FK-s 被标记为虚拟,我在同样的情况下遇到问题 - 出现一些奇怪的错误(不记得了,似乎全部是正确的,但插入失败) - 它可能只是使用 Sql CE 提供程序或更复杂的情况(例如 withMany() 为空等)。坦率地说不确定,当我管理时会尝试用一些细节来确定这一点,我只记得这是必需的事情,从那时起我将这两件事放在一起。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 2013-05-02
相关资源
最近更新 更多