【问题标题】:EF Core Include()\ThenInlude() add only one entry to each collection itemEF Core Include()\ThenInlude() 只为每个集合项添加一个条目
【发布时间】:2020-11-11 12:59:58
【问题描述】:

构建从现有数据库公开数据的 ASP.NET Core API。 所有必需的实体都基于来自几个表的数据,因此为每个实体创建了一个视图。 API 输出 - 带有实体 hierachy 的 JSON,使用 DbSet 之间的包含创建。

有父实体Projects,其中包括子Components,其中包括Users等,但它们不属于问题。简化的 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)正在处理每个组件,如果您通过关键参数查询每个 dbSet,您应该可以看到对应的数据。 项目 输出:1 个项目 -> 包含 3 个组件 -> 每个组件仅包含 1 个用户而不是两个。

我的问题是:为什么 .ThenInlcude() 每个组件只添加 User1 而忽略 User2 ?我在这里错过了什么?

如果我只查询组件 DbSet 和 Include(x=> x.usersArray) - 结果仍然相同,每个组件的 User1。另外,如果我要添加 User3、User4 - 它仍然是 User1 填充的。

当我通过 SQL 分析器找到查询时,它确实包含两个用户(由于策略,无法共享查询)。 浏览了大约 20 篇文章,但我想我在这里遗漏了一些基本的东西,如果我可以添加一些东西来使这个问题变得更好,请告诉我。

【问题讨论】:

    标签: c# entity-framework .net-core entity-framework-core


    【解决方案1】:

    它是一个关系数据库。每个深层记录都应该有所有先前级别的键。我看不到您的用户与组件的关系。如果每个用户只能在一个组件上工作或创建包含 userId 和 componentId 的 UserComponent 表以​​保持多对多关系,请添加到您的类 UserDto 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; }
             ...
        }
    

    【讨论】:

    • 感谢您的回复,我有点搞砸了,UserDTO 没有“projectId”,它是一个“componentId”,即外键。已在问题中更正。
    • 但这意味着每个用户只能在一个组件上工作。是真的吗?
    • 其实没有,每个组件可以被N个用户处理。这就是我在这里想要实现的目标,这就是为什么我建立一个(组件)到多个(用户)关系的原因。我在哪里弄错了吗?
    • 是的,正如我在回答中所说,您应该再拥有一张表 -UserComponent 来保存 userId 和 componentId
    • 非常感谢!我只是意识到我只看它的一侧,并没有意识到它应该是多对多的。
    猜你喜欢
    • 2020-03-19
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 2019-01-03
    • 2016-04-18
    • 1970-01-01
    相关资源
    最近更新 更多