2015-10-28 6 views
0

Я пытаюсь сопоставить отношения слишком много-много в C# EF с первыми миграциями кода.Entity Framework Много-много-много не заселяющих результатов

Проблема, с которой я столкнулась, заключается в том, что результаты не заселены из связанной таблицы. Возьмите этот кусок кода, например, _role не содержит права доступа, тогда как она должна содержать 4 результаты:

foreach (Role _role in _dbContext.Roles) //_dbContext.Roles.Count = 2 
{ 
    foreach(Permission _permission in _role.Permissions) //_role.Permissions.Count = 0 
    { 
     //Do something with each _permission 
    } 
} 

Классы выглядят следующим образом:

[Table("Roles")] 
public partial class Role 
{ 
    public Role() 
    { 
     Permissions = new HashSet<Permission>(); 
    } 

    [Key] 
    public int RoleId { get; set; } 

    public string RoleName { get; set; } 
    public ICollection<Permission> Permissions { get; set; } 
} 

[Table("Permissions")] 
public partial class Permission 
{ 
    public Permission() 
    { 
     Roles = new HashSet<Role>(); 
    } 

    [Key] 
    public int PermissionId { get; set; } 

    public string PermissionName { get; set; } 
    public virtual ICollection<Role> Roles { get; set; } 
} 

И, наконец, свободный API:

modelBuilder.Entity<Permission>() 
    .HasMany(e => e.Roles) 
    .WithMany(e => e.Permissions) 
    .Map(m => m 
     .ToTable("_Lnk_Role_Permission") 
     .MapLeftKey("PermissionId") 
     .MapRightKey("RoleId")); 

После проверки базы данных таблицы, ключи и данные все в порядке, и вручную добавление и запрос данных дают правильные результаты. При попытке доступа к данным, роли присутствуют, но нет разрешений.

Может ли кто-нибудь увидеть, где это может произойти неправильно?

ответ

0

После часов царапин на голове я пропустил Virtual от ICollection. Модифицированный класс выглядит так:

public partial class Role 
{ 
    public Role() 
    { 
     Permissions = new HashSet<Permission>(); 
    } 

    [Key] 
    public int RoleId { get; set; } 

    public string RoleName { get; set; } 
    public Virtual ICollection<Permission> Permissions { get; set; } //Notice the virtual?! 
} 
1

Я думаю, что вы ищете инструкцию Include.

foreach (var role in _dbContext.Roles.Include(x => x.Permissions)) 
{ 
    ... 
} 

Виртуальное ключевое слово является хорошей практикой и играет определенную роль в загрузке данных. Если вы не будете осторожны, вы можете сделать 1 + N запросов (1 для объекта Role + N больше для каждого разрешения). Оператор Include сообщает EF об эффективном объединении таблиц в запросе БД, чтобы данные были доступны в памяти для обработки ваших вложенных циклов.

Извинения за связь в другом месте, но ссылки MSDN должны быть здесь некоторое время. Это довольно хорошее чтение, чтобы понять последствия виртуального/не виртуального и с/без оператора Include: https://msdn.microsoft.com/en-us/data/jj574232.aspx

+0

Спасибо за ваш ответ. Просто чтобы прояснить в моей голове, так что должно существовать ключевое слово «Virtual», но я должен также использовать инструкцию 'Include' для загрузки данных? Спасибо – Gareth

+0

'virtual' говорит использовать ленивую загрузку для role.Permissions. В случае цикла for loop это приведет к тому, что будет выполняться 1 выбор для каждой «роли» в «Ролях» (что обычно плохо для производительности). Используя '.Include', вы эффективно сообщаете EF загружать« Роли », объединенные с« Разрешениями »одним выстрелом, поэтому тело вашего цикла не требует каких-либо взаимных отключений к базе данных. – scottt732

Смежные вопросы