具有抽象类的实体框架核心模型

时间:2019-01-06 19:55:00

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

我有一个问题

我在ASP .NET Core 2.1Entity Framework 2.1.1中建立一个代码优先数据库。现在,我正在计划中,我有一个问题。我想要一个带有方法的抽象工作者类实例的列表,该列表可以不同地工作。我的代码:

我有一个Farm

public class Farm
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual List<Farmer> Farmers { get; set; } //my problem
        public virtual List<Driver> Drivers { get; set; } //starts here!
    }

在农场实例中,我有工人。我为此做了一个abstract class

public abstract class Worker
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("Farm")]
    public int FarmId { get; set; }
    public Farm Farm { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public float UsdPerHour { get; set; }
    public int HoursPerDay { get; set; }
    public int DaysOfWork { get; set; }

    public abstract float CountSalary();
}

工作人员可以是DriverFarmer

public class Farmer : Worker
{
    public float UsdPerHour = 9;
    public int HoursPerDay = 8;
    public int DaysOfWork = 20; 
    // CountSalary() here, but in diffrent way!
}

public class Driver : Worker
{
    public float UsdPerHour = 10;
    public int HoursPerDay = 7;
    public int DaysOfWork = 18;
    // CountSalary() here, but in diffrent way!
}

还有我的FarmDbContext

public class FarmDbContext : DbContext
{
    public FarmDbContext(DbContextOptions<FarmDbContext> options) : base(options) { }

    public DbSet<Farm> Farms { get; set; }
    //public DbSet<Worker> Workers { get; set; }
    public DbSet<Farmer> Farmers { get; set; } // What to do here?
    public DbSet<Driver> Drivers { get; set; } // Let Farmers and Drivers
                                               // Or Workers?
}

在我的farm中,我有两种工人。对于每个“职位”,我想以不同的方式计算薪水。

我想在代码中做什么:

var Workers = List<Worker>
Workers.Add(New Driver());
Workers.Add(new Farmer()): 

foreach(object o in Workers)
   int salary = o.CountSalary()

// i know that code is wrong, but i describe the way that i want to achive my goal

您能解释一下我如何计划DbContext实现我想要的吗? FarmerDriver必须具有属性的硬编码值。当我在代码中像上面那样使DbContext时,我得到两个表dbo.Driversdbo.Farmers。如果它能以我上面解释的方式工作?在EF中是否可以阻止数据库中的硬编码值并将其保存在表中的每条数据记录中?

1 个答案:

答案 0 :(得分:1)

您的FarmerDriver类没有新的属性,只有一些用于计算的常量。这不是模型/数据库层的问题,而是服务层的工作。

我的建议:

public enum WorkerType
{
  Farmer,
  Driver
}

工人阶级:

public class Worker
{
  [Key]
  public int Id { get; set; }

  [ForeignKey("Farm")]
  public int FarmId { get; set; }
  public Farm Farm { get; set; }

  public string FirstName { get; set; }
  public string LastName { get; set; }
  public WorkerType WorkerType {get; set; } // assuming a worker can only be a Farmer or a Driver
}

DbContext:

public class FarmDbContext : DbContext
{
    public FarmDbContext(DbContextOptions<FarmDbContext> options) : base(options) { }

    public DbSet<Farm> Farms { get; set; }
    public DbSet<Worker> Workers { get; set; }
}

然后您可以使用一种服务或扩展方法来计算薪水,例如:

public static class WorkerExtensions
{
  public static float Salary(this Worker worker)
  {
    switch(worker.WorkerType)
    {
      case WorkerType.Farmer:
        //calculate and return

      case WorkerType.Driver:
        //calculate and return

      default:
        return -1;
    }
  }
}

现在您可以获得工人薪水:

foreach(var worker in Workers)
   var salary = worker.Salary();

这里的问题是,每次您的计算常量更改时,您都需要更改代码并重新生成/重新发布。为此,您可以在数据库中创建工资信息表并从中获取这些信息,并且可以随时更改它们。