Что мне нужно добавить в функцию OnModelCreating (DbModelBuilder modelBuilder) для определения отношений между Person и Role?
Я использую EntityFramework версии 5.0 в проекте WinForms,.net 4.5.
Я создал 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?
У человека может быть много Role (s) (но не может быть null), разные лица могут иметь одну и ту же роль (ы).
У человека может быть один "создатель" Person (может быть нулевым), у разных лиц может быть один и тот же "создатель"
Если бы вы были настолько добры, просто посоветуйте мне решение: - (
Ответы
Ответ 1
Если вы хотите использовать Fluent API для него, посмотрите этот раздел из MSDN. Вы должны использовать отношения "многие-ко-многим", а EF создаст таблицу, необходимую для случая, когда у человека может быть много ролей и роли, у которых много людей. Что-то вроде этого:
modelBuilder.Entity<Person>().HasMany(x => x.Roles).WithMany();
Также вы можете создать эти отношения без использования Fluent API. Вы должны создать свойство навигации ICollection<Person> Persons
в классе ролей, а EF также создаст соответствующую таблицу и отношения.
Ответ 2
Что-то вроде этого должно выполнить эту задачу:
Создайте POCO под названием PersonRole
. Это предназначено для моделирования отношения между a Person
и 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
используйте этот код, чтобы гарантировать, что PersonRole
будет применять свойства с нулевым значением Person
и Role
.
modelBuilder.Entity<PersonRole>().HasRequired(p => p.Person);
modelBuilder.Entity<PersonRole>().HasRequired(p => p.Role);
Edit:
Причиной создания PersonRole
POCO является обеспечение повторного использования Role
для разных пользователей. Использование существующего public virtual ICollection<Role> Role { get; set; }
будет работать, но оно, вероятно, не будет работать должным образом.
С отношением public virtual ICollection<Role> Role { get; set; }
, что EF собирается сделать, это увеличить таблицу Role
с дополнительным полем, например, PersonId
, которое будет использоваться для связи Person
с их Roles
. Проблема в этом очевидна: без привязки таблицы PersonRole
вы не сможете дать двум людям одинаковые Role
.
Ответ 3
Если вы не отвечаете на свой вопрос напрямую, используйте соглашения об именах EF, чтобы избежать Annotaions и очистите классы сущностей.
Я продемонстрирую 2 ситуации:
Один - многие используют конвенцию EF Naming Convention
Роль имеет много людей, у человека есть одна роль.
One - Many, где нет соглашения об именах (родительский ребенок того же типа)
У человека много Создано, у Человека есть один Создатель)
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:
modelBuilder.Entity<Person>()
.HasOptional(p => p.Creator)
.WithMany(p => p.Created)
.HasForeignKey(p => p.CreatorId);
С, "ClassName" + "Id" (с учетом регистра), EF будет считать, что это первичный ключ/идентификатор автоматически.
Связь Role-Person будет создана автоматически из-за виртуального сопоставления в сочетании с PrimaryKey "RoleId"