2016-11-30 118 views
0

即時播種和創建符合我的需求的數據庫。 我有2個實體;用戶和部門。 用戶需要一個部門,而一個部門可以有很多用戶,但同時部門需要一個用戶作爲其部門主管。 我可以弄清楚如何設置這個,每一次嘗試都會導致各種異常。播種代碼第一流利api數據庫EF代碼優先問題


這裏是我的背景

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

你爲什麼不在'Seed'方法中調用'SaveChanges'? –

+0

我不需要。我現在工作,我從來沒有使用保存更改:) – Bille

回答

0

那麼,您遇到所有這些錯誤,因爲你已經創建了循環需要你的實體之間的依賴關係,現在數據庫不知道如何正確插入它們。

然後,您需要稍微放鬆您的模型,以便所需的屬性之一變爲可選屬性,然後您將能夠正確地對數據庫進行種子處理。

假設您在用戶實體中將Department設置爲可選項。

此刻你讓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); 
      } 
     } 
    } 
} 

我在這裏所做的是分解任務播種成小塊,所以我首先創建首席用戶(無部門),後來我創建了部門與先前創建用戶,最後是每個部門的用戶。

這種方法的優點是您可以完全控制您創建的用戶,部門和首席。

希望這會有所幫助!