2013-10-15 55 views
1

我試圖讓1到0..1的映射在實體框架代碼中工作首先,但不斷收到錯誤: ReferentialConstraint中的依賴屬性是映射到商店生成的列。專欄:'Id'。在實體框架代碼中映射1到0..1首先

我有一個MainLocation與所需的位置,但由於位置可以有多個子位置,位置對象中不需要MainLocation。

MainLocation與MainLocationAddress具有類似的關係,但這是一個1對1的關係,它依次組成相同的數據庫表。

ER模型應該是這樣的: enter image description here

我的實體是這樣的:

[Table("MainLocation")] 
public class MainLocation : IEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    [Required] 
    public virtual MainLocationAddress Address { get; set; } 
    [Required] 
    public virtual Location Location { get; set; } 
} 

[Table("MainLocation")] 
public class MainLocationAddress : BaseAddress 
{ 
    [Key, ForeignKey("MainLocation")] 
    [DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int Id { get; set; } 
    public virtual MainLocation MainLocation { get; set; } 
} 

public class Location : IEntity 
{ 
    public int Id { get; set; } 
    public virtual Location ParentLocation { get; set; } 
    public virtual ICollection<Location> ChildLocations { get; set; } 
    protected virtual MainLocation MainLocation { get; set; } 
    internal MainLocation GetMainLocation() { return this.MainLocation; } 
    internal void SetMainLocation(MainLocation mainLocation) { MainLocation = mainLocation; } 
} 

我在我的DbContext類配置OnModelCreating消協:

modelBuilder.Entity<MainLocation>() 
      .HasRequired(x => x.Location) 
      .WithOptional(); 

modelBuilder.Entity<MainLocation>() 
      .HasRequired(x => x.Address) 
      .WithRequiredPrincipal(); 

PS!位置上的MainLocation屬性受到保護,因爲它不應該直接訪問。相反,我有一個服務層,它從位置獲取值或從ParentLocation繼承的值。我試圖將其更改爲公開,以查看它是否對我收到的錯誤進行了更改。

儘管我可以將.WithOptional()擴展爲.WithOptional(x => x.MainLocation),但在聲明的錯誤中仍然沒有任何更改。

回答

0

我已經認識到,這是不可能在EF中完成,因爲它是目前(1到0..1協會)。

我已經解決了它在我們的解決方案中讓所有的孩子的位置有一個參考的主要位置。我仍然可以通過查找沒有父母位置的地點來獲得頂級組織。所以,雖然它不是我們想要的,但它並沒有打破我們的商業模式。

1

我已經實現了兩個實體Person和User之間的1:0-1關聯。要求,用戶必須有一個且只有一個人;而一個人可能會或可能不會與用戶關聯。

public class Person 
{ 
    public int PersonId { get; set; } 
    public virtual User User { get; set; } 
} 

public class User 
{ 
    public int UserId { get; set; } 
    public int PersonId { get; set; } 
    public virtual Person Person { get; set; } 
} 

如下定義EntityTypeConfiguration類,並將它們包含在DbContext的OnModelCreating方法中。

public class PersonConfiguration : EntityTypeConfiguration<Person> 
{ 
    public PersonConfiguration() 
    { 
     ToTable("People"); 
     HasKey(p => p.PersonId); 
     Property(p => p.PersonId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     HasOptional(p => p.User).WithRequired(u => u.Person); // User is option here but 
                   // Person is required in User 
    } 

} 

public class UserConfiguration : EntityTypeConfiguration<User> 
{ 
    public UserConfiguration() 
    { 

     ToTable("Users"); 
     HasKey(u => u.UserId); 
     Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     // Create a unique index in the Users table on PersonId 
     Property(u => u.PersonId).IsRequired().HasColumnAnnotation("Index", 
      new IndexAnnotation(new IndexAttribute("IX_PersonId") { IsUnique = true })); 

    } 

} 

將下列行放在DbContext.OnModelCreating方法中。

 modelBuilder.Configurations.Add(new PersonConfiguration()); 
     modelBuilder.Configurations.Add(new UserConfiguration()); 

運行Add-Migration命令,您將在DbMigration,Up方法中獲得類似於以下內容的內容。進行如下更改。

 CreateTable(
      "dbo.Users", 
      c => new 
       { 
        Id = c.String(nullable: false, maxLength: 128), 
        PersonId = c.Int(nullable: false), 
        Person_PersonId = c.Int(nullable: false), // Delete this 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.People", t => t.Person_PersonId) // change to .ForeignKey("dbo.People", t => t.PersonId) 
      .Index(t => t.PersonId, unique: true) // append a ';' 
      .Index(t => t._Person_PersonId); // Delete this 

     CreateTable(
      "dbo.People", 
      c => new 
       { 
        PersonId = c.Int(nullable: false, identity: true), 
       }) 
      .PrimaryKey(t => t.PersonId) 

修改Down()方法如下。

變化

DropForeignKey("dbo.Users", "Person_PersonId", "dbo.People"); 

DropForeignKey("dbo.AppUsers", "PersonId", "dbo.People"); 

變化

DropIndex("dbo.AppUsers", new[] { "Person_PersonId" }); 

DropIndex("dbo.AppUsers", new[] { "PersonId" }); 

運行以此遷移爲目標的Update-Database命令。生成的用戶和人員表將在PersonId外鍵上具有一對一關聯。

0

此方案適用於更新數據庫,因爲所需的數據庫結構顯示了用戶和人員表之間的一對一關係。但是,由於某些原因試圖查詢用戶表。

我通過刪除PersonId屬性來更改User類。

public class User 
{ 
    public int UserId { get; set; } 
    public virtual Person Person { get; set; } 
} 

的UserConfiguration類變爲:

public class UserConfiguration : EntityTypeConfiguration<User> 
{ 
    public UserConfiguration() 
    { 

     ToTable("Users"); 
     HasKey(u => u.UserId); 
     Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

    } 

} 

的加載遷移生產: CREATETABLE( 「dbo.Users」, C =>新 { 編號= c.String(可爲空的:假的,最大長度:128), Person_PersonId = c.Int(可爲空的:假),//保持此 }) .PrimaryKey(T => t.UserId) .ForeignKey(「d bo.People「,t => t.Person_PersonId) .Index(t => t._Person_PersonId); //改爲.Index(t => t._Person_PersonId,unique:true);

更新數據庫生成具有一對一關係的用戶和人員表,並且該框架使用其自己生成的Person_PersonId列。