繁体   English   中英

种子代码优先流利的api数据库EF代码优先问题

[英]seeding code first fluent api database EF code-first issues

我在播种和创建符合我需要的数据库时遇到了麻烦。 我有2个实体; 用户和部门。 用户需要一个部门,一个部门可以有多个用户,但同时,一个部门需要一个用户作为其DepartmentChief。 我可以弄清楚如何进行设置,每次尝试都会导致各种异常。


这是我的情况

public class FravaerContext : DbContext
{
    public FravaerContext() : base("name=DefaultConnection")
    {
        Database.SetInitializer(new DBInitializer());
    }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasRequired<Department>(u => u.Department).WithMany(d => d.Users).WillCascadeOnDelete(false);
        modelBuilder.Entity<Department>().HasRequired(d => d.DepartmentChief);

        //modelBuilder.Entity<Absence>().HasRequired<User>(a => a.User).WithMany(u => u.Absences).WillCascadeOnDelete(false);
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Absence> Absences { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<User> Users { get; set; }

}

public class DBInitializer : DropCreateDatabaseAlways<FravaerContext>
{
    protected override void Seed(FravaerContext context)
    {
        for (int i = 1; i <= 4; i++)
        {
            User chief = new User() {Id = i, Absences = new List<Absence>(), Email = $"chief{i}@chief.dk", FirstName = $"Chief{i}",LastName = $"Chiefsen{i}",Password = "admin",UserName = ""+i,Role = Role.DepartmentChief};

            Department d = new Department() {Id = i, Users = new List<User>() { chief }, DepartmentChief = chief };


            chief.Department = d;

            context.Departments.Add(d);
        }
        base.Seed(context);
    }
}

和我的实体 (AbstractEntity仅向实体类提供ID):

  public class Department : AbstractEntity
{
    public List<User> Users { get; set; }
    public User DepartmentChief { get; set; }

}

public class User : AbstractEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public List<Absence> Absences { get; set; }
    public Department Department { get; set; }
    public Role Role { get; set; }

}

嗯,您遇到了所有这些错误,因为您已经在实体之间创建了循环所需的依赖关系,现在数据库不知道如何正确插入它们。

然后,您需要稍微放松一下模型,以便所需的属性之一变为可选,然后就可以正确地播种数据库了。

假设您在用户实体中将“部门”设置为可选。

目前,由于您没有在OnModelCreating方法上定义外键,因此让EF生成外键。

因此,首先将外键暴露给用户:

public class User : AbstractEntity
{
    public int? DepartmentId { get; set; }
}

请注意,我已将其设置为可为空,因此我们现在可以将此关系定义为可选:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasOptional(u => u.Department)
        .WithMany(d => d.Users)
        .HasForeignKey(x => x.DepartmentId)
        .WillCascadeOnDelete(false);
}

确保在Department的构造函数上初始化Users属性,以便在尝试将用户添加到Department时不会出现NullReferenceException:

public Department()
{
    Users = new List<User>();    
}

创建一个新的迁移并更新您的数据库。 然后,您可以使用以下初始化程序:

public class DBInitializer : DropCreateDatabaseAlways<FravaerContext>
{
    protected override void Seed(FravaerContext context)
    {
        //create the users first
        //save the users in a list so later we can create the departments
        var users = new List<User>();

        for (var i = 1; i <= 4; i++)
        {
            var user = new User
            {
                Id = i,
                Absences = new List<Absence>(),
                Email = $"chief{i}@chief.dk",
                FirstName = $"Chief{i}",
                LastName = $"Chiefsen{i}",
                Password = "admin",
                UserName = "user" + i,
                Role = Role.DepartmentChief
            };
            users.Add(user);
            context.Users.Add(user);
        }

        //create one department for each user (with that user as the chief)
        var departmentId = 1;

        //save the departments so later we can seed them with users
        var departments = new List<Department>();
        foreach (var user in users)
        {
            var d = new Department
            {
                Id = departmentId++,
                DepartmentChief = user
            };

            departments.Add(d);
            context.Departments.Add(d);
        }

        //seeed the departments with users
        foreach (var department in departments)
        {
            //add 5 users to each department
            for (var i = 1; i < 5; i++)
            {
                var user = new User
                {
                    Absences = new List<Absence>(),
                    Email = $"user{department.Id}{i}@user.dk",
                    FirstName = $"User{department.Id}{i}",
                    LastName = $"Username{department.Id}{i}",
                    Password = "user",
                    UserName = "" + department.Id + i,
                    Role = Role.DepartmentChief
                };
                department.Users.Add(user);
            }
        }
    }
}

我在这里所做的是将播种任务分解为较小的部分,因此我首先创建主要用户(不包含部门),然后创建具有先前创建的用户的部门,最后创建每个部门的用户。

这种方法的优点是您可以完全控制创建的用户,部门和负责人的数量。

希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM