2017-02-27 50 views
1

我目前有2個模型需要運行遷移到一個新的數據庫,而且我沒有得到我期望的結構。我很抱歉,如果這是一個簡單的答案,我對Code First with Entity Framework相當陌生。代碼首先遷移不應該存在的外鍵

首先我有一個User對象。這只是應該有一個UserID一個主鍵,然後某些字段填寫。

public class User : CustomDataEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int UserID { get; set; } 
    public string Username { get; set; } 
    public string Password { get; set; } 
    public DateTime Birthday { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string EmailAddress { get; set; } 
    public byte[] Picture { get; set; } 
} 

然後,我有一個Event對象。這應該有一個EventID作爲主鍵,然後我試着擁有一個ForeignKey'd HostUser以及存儲在RegisteredUsers表中的註冊該事件的用戶列表。

public class Event : CustomDataEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int EventID { get; set; } 
    [ForeignKey("HostUser")] 
    public int HostUserID { get; set; } 
    [ForeignKey("RegisteredUsers")] 
    public ICollection<int> RegisteredUserIDs { get; set; } 
    public virtual User HostUser { get; set; } 
    public string Description { get; set; } 
    public virtual ICollection<User> RegisteredUsers { get; set; } 
} 

基於關閉的這一點,我會希望有UserEvent表的數據庫結構,在dbo.EventUser表的外鍵列(外鍵HostUserID),以及一個查找表將用戶列表映射到事件(用於RegisteredUsers的列表)。

問題是,當我基於此結構創建遷移時,我得到以下用於Up()部件的CreateTable方法。

public override void Up() 
    { 
     CreateTable(
      "dbo.Event", 
      c => new 
       { 
        EventID = c.Int(nullable: false, identity: true), 
        HostUserID = c.Int(nullable: false), 
        Description = c.String(nullable: false), 
        NumberOfUsers = c.Int(nullable: false), 
        StartDate = c.DateTime(nullable: false), 
        EndDate = c.DateTime(), 
        CreatedAt = c.DateTimeOffset(precision: 7, 
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "CreatedAt") 
          }, 
         }), 
        Deleted = c.Boolean(nullable: false, 
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "Deleted") 
          }, 
         }), 
        Id = c.String(
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "Id") 
          }, 
         }), 
        UpdatedAt = c.DateTimeOffset(precision: 7, 
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "UpdatedAt") 
          }, 
         }), 
        Version = c.Binary(
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "Version") 
          }, 
         }), 
       }) 
      .PrimaryKey(t => t.EventID) 
      .ForeignKey("dbo.User", t => t.HostUserID, cascadeDelete: true) 
      .Index(t => t.HostUserID); 

     CreateTable(
      "dbo.User", 
      c => new 
       { 
        UserID = c.Int(nullable: false, identity: true), 
        Username = c.String(nullable: false), 
        Password = c.String(nullable: false), 
        Birthday = c.DateTime(nullable: false), 
        FirstName = c.String(nullable: false), 
        LastName = c.String(nullable: false), 
        EmailAddress = c.String(nullable: false), 
        Picture = c.Binary(), 
        CreatedAt = c.DateTimeOffset(precision: 7, 
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "CreatedAt") 
          }, 
         }), 
        Deleted = c.Boolean(nullable: false, 
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "Deleted") 
          }, 
         }), 
        Id = c.String(
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "Id") 
          }, 
         }), 
        UpdatedAt = c.DateTimeOffset(precision: 7, 
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "UpdatedAt") 
          }, 
         }), 
        Version = c.Binary(
         annotations: new Dictionary<string, AnnotationValues> 
         { 
          { 
           "ServiceTableColumn", 
           new AnnotationValues(oldValue: null, newValue: "Version") 
          }, 
         }), 
        Event_EventID = c.Int(), 
       }) 
      .PrimaryKey(t => t.UserID) 
      .ForeignKey("dbo.Event", t => t.Event_EventID) 
      .Index(t => t.Event_EventID); 

    } 

最後兩行是我要重點

.ForeignKey("dbo.Event", t => t.Event_EventID) 
.Index(t => t.Event_EventID); 

這是建立在用戶表事件表一個ForeignKey的那些,即使我沒有Event_EventID定義做用戶模型的任何位置。我認爲Migration假設用戶一次只能註冊1個事件,因爲我沒有看到任何查找表來確定哪些用戶註冊了哪些事件。

我試過把我的Event模型搞亂,把ForeignKey屬性直接放在RegisteredUsers對象上,發現這個錯誤非常快。

我該如何強制EF認識到我需要一個多對多的用戶關係事件關係?或者我是否認爲這是問題而吠叫錯誤的樹?

EDIT

我除去ForeignKey屬性和設置ICollection的每個,並且我仍然有相同的錯誤,除了現在我有一個附加列,僅允許每個事件的單個用戶,並沒有EventUsers表。

public class User : CustomDataEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int UserID { get; set; } 
    public string Username { get; set; } 
    public string Password { get; set; } 
    public DateTime Birthday { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string EmailAddress { get; set; } 
    public byte[] Picture { get; set; } 
    public virtual ICollection<Event> EventsRegisteredFor { get; set; } 
} 

public class Event : CustomDataEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int EventID { get; set; } 
    public virtual User HostUser { get; set; } 
    public string Description { get; set; } 
    public virtual ICollection<User> RegisteredUsers { get; set; } 
} 

和我結束了

 CreateTable(
      "dbo.Event", 
      c => new 
       { 
        EventID = c.Int(nullable: false, identity: true), 
        Description = c.String(nullable: false), 
        NumberOfUsers = c.Int(nullable: false), 
        StartDate = c.DateTime(nullable: false), 
        EndDate = c.DateTime(), 
        User_UserID = c.Int(), 
        HostUser_UserID = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.EventID) 
      .ForeignKey("dbo.User", t => t.User_UserID) 
      .ForeignKey("dbo.User", t => t.HostUser_UserID, cascadeDelete: true) 
      .Index(t => t.User_UserID) 
      .Index(t => t.HostUser_UserID); 

     CreateTable(
      "dbo.User", 
      c => new 
       { 
        UserID = c.Int(nullable: false, identity: true), 
        Username = c.String(nullable: false), 
        Password = c.String(nullable: false), 
        Birthday = c.DateTime(nullable: false), 
        FirstName = c.String(nullable: false), 
        LastName = c.String(nullable: false), 
        EmailAddress = c.String(nullable: false), 
        Picture = c.Binary(), 
        Event_EventID = c.Int(), 
       }) 
      .PrimaryKey(t => t.UserID) 
      .ForeignKey("dbo.Event", t => t.Event_EventID) 
      .Index(t => t.Event_EventID); 

EDIT 2 我經歷了,並得到我的模型到最基礎的信息,我可以使用。

public class User : CustomDataEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int UserID { get; set; } 
    public string Username { get; set; } 
    public virtual List<Event> Events { get; set; } 
} 
public class Event : CustomDataEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int EventID { get; set; } 
    public virtual User HostUser { get; set; } 
    public virtual List<User> Users { get; set; } 
} 

但是,這種結構仍然不給我一點EventUsers或UserEvents表,它只是增加了一列的數據庫,它允許單個用戶名

public override void Up() 
    { 
     CreateTable(
      "dbo.Event", 
      c => new 
       { 
        EventID = c.Int(nullable: false, identity: true), 
        User_UserID = c.Int(), 
        HostUser_UserID = c.Int(), 
       }) 
      .PrimaryKey(t => t.EventID) 
      .ForeignKey("dbo.User", t => t.User_UserID) 
      .ForeignKey("dbo.User", t => t.HostUser_UserID) 
      .Index(t => t.User_UserID) 
      .Index(t => t.HostUser_UserID); 

     CreateTable(
      "dbo.User", 
      c => new 
       { 
        UserID = c.Int(nullable: false, identity: true), 
        Username = c.String(), 
        Event_EventID = c.Int(), 
       }) 
      .PrimaryKey(t => t.UserID) 
      .ForeignKey("dbo.Event", t => t.Event_EventID) 
      .Index(t => t.Event_EventID); 

    } 

回答

0

對於多對多 - 許多的關係,只是添加在每個模型的集合:

用戶添加到模型:

公共虛擬ICollection的活動{設置;得到; } //多到許多

和事件模型添加:

公共虛擬ICollection的用戶{設置;得到; } //多對多


您不需要使用任何其他外鍵。

實體框架會自動創建EventUsers表,並且無法從您的dbcontext訪問此表。 (你不需要太多訪問)

但是如果你想訪問EventUsers表,你應該從用戶和事件中刪除多對多的關係,創建一個新的模型,例如EventUsers,並創建一個到多個關係用戶到事件用戶和從事件到事件用戶。

+0

我想這隻能創建一個關係是多對多的,和我結束了同樣的問題,除了現在我還有一個User_UserID列在數據庫中,每個事件只允許1個用戶。我將把我的代碼放在Edit –

0
在多對多的關係就會創建一個第三表,其包括兩個表的主鍵,例如,這意味着可以在用戶

public class User 
{ 
    [Key] 
    public int UserID { get; set; } 
    public string Username { get; set; } 
    public List<Event> Events { get; set; } 
} 
public class Event 
{ 
    [Key] 
    public int EventID { get; set; } 
    public List<User> Users { get; set; } 
} 

注意,i的user類使用的事件的listevent類相同

有很多事件,一個事件可以有很多用戶(many to many) ,所以當我添加遷移時,它將創建第三個表名UserEvent,這將包括這兩個表的外鍵。

編輯

您使用public virtual User HostUser { get; set; }它創造了一對多的關係,這樣你就綁所以沒有必要的public virtual User HostUser { get; set; }

+0

中,不需要[DatabaseGenerated(DatabaseGeneratedOption.Identity)]和:CustomDataEntity – Usman

+0

我需要「ITableData」而不是CustomDataEntity嗎? –

+0

不,你不需要放任何東西dbcontext將處理它當你在dbset中添加模型 – Usman

相關問題