20

我在 WinForms 项目 .net 4.5 中使用 EntityFramework 5.0 版。

我为我创建了 2 个重要实体

    public class Role
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }
        public bool StockPermission { get; set; }
        public bool ItemPermission { get; set; }
        public bool OrderPermission { get; set; }
        public bool PersonPermission { get; set; }
        public bool StatisticPermission { get; set; }
    }

    public class Person
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public String Name { get; set; }
        public String Nickname { get; set; }
        public String Contact { get; set; }
        public System.DateTime Created { get; set; }
        public String Pincode { get; set; }

        public virtual ICollection<Role> Role { get; set; }
        public virtual Person Creator { get; set; }
    }

和 dbContext 类:

    public class SusibarDbContext : DbContext
    {
        public DbSet<Entity.Role> Roles { get; set; }
        public DbSet<Entity.Person> Persons { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //base.OnModelCreating(modelBuilder);
        }
    }

拜托,你能帮我在OnModelCreating(DbModelBuilder modelBuilder)函数中添加什么来定义Person和Role之间的关系吗?

Person 可以有多个 Role(s)(但不能为 null),不同的 Person 可以有相同的 Role(s)。

Person 可以有一个“创建者”Person(可以为 null),不同的 Person 可以有相同的“创建者”

如果你能这么好,请告诉我解决方案:-(

4

3 回答 3

17

如果您想为此使用 Fluent API,请查看 MSDN 中的此主题。您应该使用多对多关系,并且 EF 将创建一个表,以应对 Person 可以拥有多个角色且角色拥有多个 Person 的情况。像这样的东西:

modelBuilder.Entity<Person>().HasMany(x => x.Roles).WithMany();

您也可以在不使用 Fluent API 的情况下创建这种关系。您应该在 Role 类中创建导航属性ICollection<Person> Persons,EF 也会创建适当的表和关系。

于 2012-12-08T08:59:57.003 回答
1

像这样的东西应该可以完成这项工作:

创建一个名为PersonRole. 这是为了模拟 aPerson和 a之间的关系Role

public class PersonRole
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public Person Person { get; set; }
    public Role Role { get; set; }
}

Person类中,替换:

public virtual ICollection<Role> Role { get; set; }

和:

public virtual ICollection<PersonRole> PersonRoles { get; set; }

如果你愿意,你可以在Role类中添加以下内容:

public virtual ICollection<PersonRole> PersonRoles { get; set; }

这样做是可选的,但如果您希望People使用部分Role.

OnModelCreating方法中,使用此代码确保 aPersonRole将强制执行不可为空PersonRole属性。

modelBuilder.Entity<PersonRole>().HasRequired(p => p.Person);
modelBuilder.Entity<PersonRole>().HasRequired(p => p.Role);

编辑:

创建 POCO 的原因PersonRole是为了确保 aRole可以在不同用户之间重复使用。使用现有的public virtual ICollection<Role> Role { get; set; }将起作用,但它可能不会按预期工作。

有了关系public virtual ICollection<Role> Role { get; set; },EF 要做的是Role用一个额外的字段来扩充表,例如,PersonId,它将用于将 aPerson与它们的相关联Roles。这样做的问题很明显:没有链接PersonRole表,您将无法为两个人提供相同的Role.

于 2012-12-07T01:16:45.960 回答
1

尽管不能直接回答您的问题,但请使用 EF 命名约定来避免注释并保持实体类的清洁。我将演示两种情况:

一 - 许多使用 EF 命名约定

角色有很多人,人只有一个角色

一 - 许多不存在命名约定的地方(相同类型的父子)

人有很多创造者,人有一个创造者)

public class Role
{
    public int RoleId { get; set; }
    public string Name { get; set; }
    ...

    public virtual ICollection<Person> Persons { get; set; }
}

public class Person
{
    public int PersonId { get; set; }
    public int CreatorId { get; set; } 
    public int RoleId { get; set; } 
    ...

    public virtual Role Role { get; set; }
    public virtual Person Creator { get; set; }
    public virtual ICollection<Person> Created { get; set; }
}

对于 OnModelCreating 中的 Creator-Created 关系:

modelBuilder.Entity<Person>()
    .HasOptional(p => p.Creator)
    .WithMany(p => p.Created)
    .HasForeignKey(p => p.CreatorId);

使用“ClassName”+“Id”(区分大小写),EF 将自动假定它是主键/标识符。由于虚拟映射与 PrimaryKey "RoleId" 结合,将自动创建 Role-Person 关系

于 2013-04-19T10:56:31.857 回答