实体框架核心-设置Table1.Column = Table2.Column

时间:2020-08-22 05:53:09

标签: c# linq entity-framework-core

我正在使用.Net Core 3.1和Entity Framework Core

我有以下型号:

public Employee {
      ...
      public string PositionName { get; set; }
      public int PositionId { get; set; }
      ...
}

public Position {
     public int Id { get; set; }
     public string Name { get; set; }
}

其中Position.Id与Employee.PositionId相关

我的目标是从职位表(非常小的表-10行)中将Employee的IEnumerable返回给用户,Employee.PositionName = Position.Name。

我使用以下方法蛮力实现了这一点:

   IEnumerable<Employee> employees = await repository.GetAllAsync();
   IEnumerable<Position> positions = await positionRepository.GetAllAsync();

   foreach (Employee emp in employees)
   {
       emp.PositionName = positions.FirstOrDefault(position => position.Id == employee.PositionId).Name;
   }

如果两个表都很大,那么这是一个糟糕的解决方案。

有什么建议吗?

3 个答案:

答案 0 :(得分:0)

也许是这样的:

var filtered = employees.Where(x => positions.Any(n=>n.Name.Equals(x.PositionName)));

有点题外话,但最好使用.ConfigureAwait(false);。以确保在数据提取期间不会发生意外情况。

答案 1 :(得分:0)

我建议您为要创建的数据创建一个新模型。两个表都说NewModel然后查询它:

var query = from emp in your_context.repository
                    join pos in your_context.positionRepository
                    on emp.PositionId  equals pos.Id
                    select new NewModel
                    {
                        // any data you want 
                        EmpName = emp.Emp_Name,
                        EmpPos = pos.Emp_Pos,

                    };
        List<NewModel> emplist = query.ToList(); 

答案 2 :(得分:0)

感谢您的回复。在弄清楚这一点之前,我还没有看到它们。

我需要在模型中建立一对多的关系。

有几种方法可以做到这一点。我选择创建一个“有一个”关系,在其中“员工”有一个“职位”。

   public Employee 
   {
      public int Id {get; set;}
     ...other props here....

      // EF will automatically create a foreign key because the Position Model has Id
      public Position Position{ get; set; }
   }

   public Position {
      public int Id { get; set; }
      public string Name { get; set; }
   }

注意:EF将自动创建外键关系 员工表和职位表之间的关系,只要职位 表/模型具有适当的ID(Id或PositionId)。

播种我的数据库时,我只是简单地创建了employees及其职位,并填充了两个表:

       using (var transaction = context.Database.BeginTransaction())
        {
            context.Employee.AddRange(new Employee[] {
                new Employee{
                    ..other fields initialized here...
                    Position = new Position { Name = "Manager" }
                },
                new Employee{
                      ..other fields initialized here...
                    Position = new Position { Name = "Supervisor" }
                }

            });

            context.SaveChanges();


            transaction.Commit();
        }

注意:显然,最好创建Position表并填充 分开。我必须为每个职位创建一个员工 使用上面的方法进行输入。

进一步研究之后,我终于找到了一种更好的方法来配置此相关的Entity关系,方法是在Employee模型中为Position.Id添加外键ID:

   public Employee 
   {
      public int Id {get; set;}
     ...other props here....

      // EF will treat PositionId as the Foreign Key
      public int PositionId {get; set;}
      public Position Position{ get; set; }
   }

   public Position {
      public int Id { get; set; }
      public string Name { get; set; }
   }

然后,我首先播种位置表。我将创建的每一行的ID存储在变量中,以在下面设置Employee.PositionId。 (例如managerId,ceoId)

然后我将Employee表植入如下:

    using (var transaction = context.Database.BeginTransaction())
        {
            context.Employee.AddRange(new Employee[] {
                new Employee{
                    ..other fields initialized here...
                    PositionId = managerId
                },
                new Employee{
                      ..other fields initialized here...
                    PositionId = ceoId
                }

            });

            context.SaveChanges();

            transaction.Commit();
        }

下一个问题:如何获取Linq返回相关的Position实体。

然后,我在这里找到了一些有关如何从排名表中加载相关数据的帮助: https://docs.microsoft.com/en-us/ef/core/querying/related-data

DbSet dbEntity = context.Set();

此Linq语句不会带回相关数据

IEnumerable<Employee> employees = dbEntity.ToList();

输入急切加载 为此,我们需要使用“包含” Linq扩展名来使用“急切加载”:

IEnumerable<Employee> employees = dbEntity.Include(e => e.Position).ToList();

有什么想法吗?有想法吗?让我知道您是否有更好的解决方案。