#c# #entity-framework #.net-core #entity-framework-core
#c# #entity-framework #.net-ядро #entity-framework-core
Вопрос:
Построение ASP.NET Основной API, который предоставляет данные из существующей базы данных. Все необходимые объекты основаны на данных из нескольких таблиц, поэтому для каждого создано представление. Вывод API — JSON с объектами hirerachy, созданными с использованием includes между наборами баз данных.
Существует родительская сущность Projects, которая включает дочерние компоненты, в которую входят пользователи, и некоторые другие, но они не являются частью проблемы. Упрощенные DTO:
public class RrojectDTO
{
public int projectId { get; set; }
public string componentCode { get; set; }
public virtual ICollection<ComponentDTO> componentsArray { get; set; }
}
public class ComponentDTO
{
public Guid componentId { get; set; }
public virtual RrojectDTO Project { get; set; }
public string componentCode { get; set; }
public virtual ICollection<UserDTO> usersArray { get; set; }
...
}
public class UserDTO
{
public int userId { get; set; }
public virtual ComponentDTO Component { get; set; }
public Guid componentId { get; set; }
...
}
Вот как выглядит класс DbContext:
public MyDbContext(DbContextOptions options)
: base(options)
{
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTrackingWithIdentityResolution;
}
public virtual DbSet<ProjectDTO> Projects{ get; set; }
public virtual DbSet<ComponentDTO> Components { get; set; }
public virtual DbSet<UserDTO> Users { get; set; }
....
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProjectDTO>(entity =>
{
entity.HasKey(f => f.componentCode);
entity.ToView("ProjectsArrayView", "LAB");
entity.HasMany(p => p.componentsArray).WithOne(t => t.Project)
.HasForeignKey(t => t.componentCode);
});
modelBuilder.Entity<ComponentDTO>(entity =>
{
entity.HasKey(f => f.componentId);
entity.ToView("ComponentArrayView", "LAB");
entity.HasMany(p => p.usersArray).WithOne(t => t.Component)
.HasForeignKey(t => t.componentId);
....
});
modelBuilder.Entity<UserDTO>(entity =>
{
entity.HasKey(f => f.userId);
entity.ToView("UsersArrayView", "LAB");
...
});
Я соединяю эти объекты со следующим кодом:
`var projects = context.Projects.Where(p => p.projectId == Guid.Parse("9C373F8F-CAB8-4914-83D9-4864B2E3E7B3")).Include(co => co.componentsArray).ThenInclude(j => j.usersArray).ToList();`
Изначально в проект включено больше, но другие, похоже, работают нормально. Хотя один из примеров работает не так, как ожидалось, например: есть один проект, в котором есть 3 компонента, те же 2 пользователя (User1 и User2) работают над каждым компонентом, если вы запрашиваете каждый набор баз данных по ключевым параметрам, вы должны иметь возможность видеть соответствующие данные. результат проекта: 1 проект -> с 3 компонентами -> каждый компонент содержит только 1 пользователя вместо двух.
Мой вопрос: почему.ThenInlcude() добавляет только User1 для каждого компонента, но игнорирует User2 ? чего мне здесь не хватает?
Если я запрашиваю только компоненты DbSet и Include(x=> x.usersArray) — результат все тот же, Пользователь1 на компонент. Кроме того, если я добавляю User3, User4 — все равно заполняется User1.
Когда я нашел запрос через SQL profiler, он содержал обоих пользователей (не может поделиться запросом из-за политик). Просмотрел около 20 статей, но я думаю, что мне здесь не хватает чего-то основного, пожалуйста, дайте мне знать, если я могу что-то добавить, чтобы улучшить это qeustion.
Ответ №1:
Это реляционная база данных. Каждая запись глубокого уровня должна иметь ключи всех предыдущих уровней. Я не понимаю, как ваш пользователь связан с компонентом. Добавьте в свой класс внешний ключ UserDTO componentID, если каждый пользователь может работать только с одним компонентом, или создайте таблицу UserComponent, содержащую userId и componentID, чтобы сохранить отношение «многие ко многим».
public class UserDTO
{
public int userId { get; set; }
public int componentId {get;set;}
public virtual ComponentDTO Component { get; set; }
public Guid projectId { get; set; }
...
}
Комментарии:
1. Спасибо за ваш ответ, я немного перепутал, у UserDTO нет «ProjectID», это «componentID», который является внешним ключом. Исправлено в вопросе.
2. Но это означает, что каждый пользователь может работать только с одним компонентом. Это правда?
3. На самом деле нет, каждый компонент может обрабатываться N пользователями. Это то, чего я пытаюсь достичь здесь, и именно поэтому я создаю отношения один (компонент) для многих (пользователей). Я где-то ошибаюсь?
4. Да, как я уже сказал в своем ответе, тогда у вас должна быть еще одна таблица -UserComponent, содержащая userId и componentID
5. Большое вам спасибо! Я только что понял, что я смотрел только на одну сторону и не понял, что это должно быть много-ко-многим.