2016-11-30 8 views
0

私のニーズに合ったデータベースを作成して作成することに問題があります。 私は2つのエンティティを持っています。ユーザーと部門。 ユーザーには部署が必要であり、部門には多数のユーザーが存在することができますが、同時に部署には1人のユーザーが部門責任者になる必要があります。 私はこれをどのように設定できるかを理解することができます。あらゆる試みが様々な種類の例外をもたらしました。シードコード最初の流暢な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をオプションとして設定したとします。

現在のところ、OnModelCreatingメソッドで定義していない外来キーを生成するようにEFに指示しています。

だからあなたのユーザーにあなたの外部キーを暴露することによって起動します。私は、我々は今、オプションとして、この関係を定義することができますnullとして、それを設定した

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); 
      } 
     } 
    } 
} 

は小さな部分に播種タスクを分解しているので、私は最初の(無部門と)チーフのユーザーを作成し、後で私が以前に部署を作成します作成されたユーザー、最後に各部門のユーザーが含まれます。

この方法の利点は、作成するユーザー、部門、および首長の数を完全に制御できることです。

希望すると便利です。

関連する問題