我无法播种并创建符合我需求的数据库。 我有2个实体;用户和部门。 用户需要一个部门,一个部门可以有很多用户,但同时,一个部门需要一个用户作为其部门。 我可以弄清楚如何设置它,每次尝试都会导致各种异常。
这是我的上下文:
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; }
}
答案 0 :(得分:0)
嗯,您已经遇到了所有这些错误,因为您已经在实体之间创建了循环所需的依赖关系,现在数据库还不知道如何正确插入它们。
然后您需要稍微松开模型,以便其中一个必需属性成为可选项,然后您就可以正确地为数据库设定种子。
我们假设您在用户实体中将部门设置为可选。
目前,您正在让EF生成您的外键,因为您没有在OnModelCreating方法上定义它。
首先将您的外键暴露给您的用户:
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属性,这样您就不会尝试将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);
}
}
}
}
我在这里所做的是将播种任务分解成更小的部分,所以我首先创建主要用户(没有部门),之后我用先前创建的用户创建部门,最后创建每个部门的用户
此方法的优点是您可以完全控制您创建的用户,部门和负责人的数量。
希望这有帮助!