1

我一直在拉我的頭髮,試圖找出我認爲會是一個相對簡單的關係映射(一對多)。EF 6關係:在模型生成期間檢測到一個或多個驗證錯誤

咱們過去我有什麼在車型:

ContentExternalLink

public class ContentExternalLink 
{ 
    public ContentExternalLink() 
    { 
     ContentTagAssignments = new List<ContentTagAssignment>(); 
    } 

    [Key] 
    public string LinkId { get; set; } 
    public string LinkTypeId { get; set; } 
    public string LinkTitle { get; set; } 
    public string LinkUrl { get; set; } 
    public string LinkSource { get; set; } 
    public string LinkPhoneNumber { get; set; } 
    public DateTime LinkDate { get; set; } 
    public DateTime LinkCreatedDate { get; set; } 
    public DateTime LinkModifiedDate { get; set; } 
    [ScriptIgnore] 
    public virtual ICollection<ContentTagAssignment> ContentTagAssignments { get; set; } 
} 

ContentTagAssignmnent

public class ContentTagAssignment 
{ 
    public ContentTagAssignment() 
    { 
     this.ContentExternalLink = new ContentExternalLink(); 
    } 

    [Key] 
    public string TagId { get; set; } 
    [Key] 
    public string ArticleId { get; set; } 
    public bool IsPrimary { get; set; } 
    public DateTime CreatedDate { get; set; } 
    [ScriptIgnore] 
    public virtual ContentExternalLink ContentExternalLink { get; set; } 
} 

現在到映射:

ContentExternalLinkMap

public class ContentExternalLinkMap : EntityTypeConfiguration<ContentExternalLink> 
{ 
    public ContentExternalLinkMap() 
    { 
     this.ToTable("content_external_link", "dbo"); 

     this.HasKey(c => c.LinkId); 

     this.Property(c => c.LinkId).HasColumnName("link_id"); 
     this.Property(c => c.LinkTypeId).HasColumnName("link_type_id"); 
     this.Property(c => c.LinkTitle).HasColumnName("link_title"); 
     this.Property(c => c.LinkUrl).HasColumnName("link_url"); 
     this.Property(c => c.LinkSource).HasColumnName("link_source"); 
     this.Property(c => c.LinkPhoneNumber).HasColumnName("link_phone_number"); 
     this.Property(c => c.LinkDate).HasColumnName("link_date"); 
     this.Property(c => c.LinkCreatedDate).HasColumnName("link_created_date"); 
     this.Property(c => c.LinkModifiedDate).HasColumnName("link_modified_date"); 
    } 
} 

ContentTagAssignmnetMap

public class ContentTagAssignmentMap : EntityTypeConfiguration<ContentTagAssignment> 
{ 
    public ContentTagAssignmentMap() 
    { 
     this.ToTable("content_tag_assignment", "dbo"); 

     this.HasKey(t => new {t.TagId, t.ArticleId}); 

     this.Property(t => t.TagId).HasColumnName("tag_id"); 
     this.Property(t => t.ArticleId).HasColumnName("article_id"); 
     this.Property(t => t.IsPrimary).HasColumnName("is_primary_tag"); 
     this.Property(t => t.CreatedDate).HasColumnName("created_date"); 


     this.HasOptional(t => t.ContentExternalLink) 
      .WithMany(t => t.ContentTagAssignments) 
      .HasForeignKey(t => new {t.TagId, t.ArticleId}); 
    } 
} 

的關係肯定是怪異的一側在LINKID將匹配在ContentTagAssignment條款ArticleID。

我試過在ContentTagAssignmentMap如下:

//this.HasOptional(t => t.ContentExternalLink) 
// .WithMany(t => t.ContentTagAssignments) 
// .HasForeignKey(t => t.ContentExternalLink); 

this.HasOptional(x => x.ContentExternalLink) 
    .WithMany(x=>x.ContentTagAssignments) 
    .Map(x => x.MapKey("LinkId").HasColumnAnnotation("LinkId","ArticleId",null)); 

//this.Map(m => 
// { 
//  m.Properties(x => x.ArticleId); 
//  m.ToTable("content_tag_assignment"); 
// }) 
// .Map(p => 
// { 
//  p.Properties(x => x.ContentExternalLink.LinkId); 
//  p.ToTable("ContentExternalLink"); 
// }); 

註釋的關係不起作用。一個工作(因爲它不會在初始頁面加載失敗)。但是,當我嘗試從ContentExternalLink訪問列表時,出現以下錯誤:{「列名無效'LinkId'。\ r \ n列名'LinkId'。」}

因此,我甚至更多輸了...

問題

基本上,不是每個ContentExternalLink都會有一個標籤分配給它。但是,如果對ContentExternalLink有ContentTagAssignments,我應該能夠獲得它們的列表。另外,TagId和ArticleId是字符串(guid)。

有沒有人有任何建議?

謝謝!

+0

你已經證明這兩種型號都相同('ContentTagAssignmnent'):) –

+0

@StephenMuecke衛生署!感謝您告訴我,我已經用真實模型更新了ContentExternalLink模型。 – ajtatum

+0

http://stackoverflow.com/q/20757594/861716 –

回答

2

ivan stoev的意見後,我看到,這裏的唯一錯誤是設置可選當外鍵都是主鍵(not nullable

這樣的映射將是:

public class ContentTagAssignmentMap : EntityTypeConfiguration<ContentTagAssignment> 
{ 
    public ContentTagAssignmentMap() 
    { 
     this.ToTable("content_tag_assignment", "dbo"); 

     this.HasKey(t => new { t.TagId, t.ArticleId }); 

     this.Property(t => t.TagId).HasColumnName("tag_id"); 
     this.Property(t => t.ArticleId).HasColumnName("article_id"); 
     this.Property(t => t.IsPrimary).HasColumnName("is_primary_tag"); 
     this.Property(t => t.CreatedDate).HasColumnName("created_date"); 


     this.HasRequired(t => t.ContentExternalLink) 
      .WithMany(t => t.ContentTagAssignments) 
      .HasForeignKey(t => t.ArticleId) 
      .WillCascadeOnDelete(false); 
    } 
} 

以下與模型的工作示例:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var ctx = new Context(); 
     ctx.Database.Delete(); 
     ctx.Database.CreateIfNotExists(); 

     Console.ReadKey(); 
    } 
} 

public class Context : DbContext 
{ 
    public Context():base ("Teste") 
    { 

    } 

    public DbSet<ContentExternalLink> ContentExternalLinks { get; set; } 
    public DbSet<ContentTagAssignment> ContentTagAssignments { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new ContentExternalLinkMap()); 
     modelBuilder.Configurations.Add(new ContentTagAssignmentMap()); 

     base.OnModelCreating(modelBuilder); 
    } 

} 

public class ContentExternalLink 
{ 
    public ContentExternalLink() 
    { 
     ContentTagAssignments = new List<ContentTagAssignment>(); 
    } 

    [Key] 
    public string LinkId { get; set; } 
    public string LinkTypeId { get; set; } 
    public string LinkTitle { get; set; } 
    public string LinkUrl { get; set; } 
    public string LinkSource { get; set; } 
    public string LinkPhoneNumber { get; set; } 
    public DateTime LinkDate { get; set; } 
    public DateTime LinkCreatedDate { get; set; } 
    public DateTime LinkModifiedDate { get; set; } 

    public virtual ICollection<ContentTagAssignment> ContentTagAssignments { get; set; } 
} 

public class ContentTagAssignment 
{ 
    public ContentTagAssignment() 
    { 
     this.ContentExternalLink = new ContentExternalLink(); 
    } 

    [Key] 
    public string TagId { get; set; } 
    [Key] 
    public string ArticleId { get; set; } 
    public bool IsPrimary { get; set; } 
    public DateTime CreatedDate { get; set; } 

    public virtual ContentExternalLink ContentExternalLink { get; set; } 
} 

public class ContentExternalLinkMap : EntityTypeConfiguration<ContentExternalLink> 
{ 
    public ContentExternalLinkMap() 
    { 
     this.ToTable("content_external_link", "dbo"); 

     this.HasKey(c => c.LinkId); 

     this.Property(c => c.LinkId).HasColumnName("link_id"); 
     this.Property(c => c.LinkTypeId).HasColumnName("link_type_id"); 
     this.Property(c => c.LinkTitle).HasColumnName("link_title"); 
     this.Property(c => c.LinkUrl).HasColumnName("link_url"); 
     this.Property(c => c.LinkSource).HasColumnName("link_source"); 
     this.Property(c => c.LinkPhoneNumber).HasColumnName("link_phone_number"); 
     this.Property(c => c.LinkDate).HasColumnName("link_date"); 
     this.Property(c => c.LinkCreatedDate).HasColumnName("link_created_date"); 
     this.Property(c => c.LinkModifiedDate).HasColumnName("link_modified_date"); 
    } 
} 

public class ContentTagAssignmentMap : EntityTypeConfiguration<ContentTagAssignment> 
{ 
    public ContentTagAssignmentMap() 
    { 
     this.ToTable("content_tag_assignment", "dbo"); 

     this.HasKey(t => new { t.TagId, t.ArticleId }); 

     this.Property(t => t.TagId).HasColumnName("tag_id"); 
     this.Property(t => t.ArticleId).HasColumnName("article_id"); 
     this.Property(t => t.IsPrimary).HasColumnName("is_primary_tag"); 
     this.Property(t => t.CreatedDate).HasColumnName("created_date"); 


     this.HasRequired(t => t.ContentExternalLink) 
      .WithMany(t => t.ContentTagAssignments) 
      .HasForeignKey(t => t.ArticleId) 
      .WillCascadeOnDelete(false); 
    } 
} 

這裏從上面的代碼的結果:

Created Tables

+0

中,一對多隻是一個外鍵(一個的指導)。對不起,我恢復了建議的更改。FK總是處於'many'側,所以它不能是'LinkId'。 –

+0

它是可選方面的關鍵,它引用了您將要使用的許多方面。您需要引用ContentExternalLink的ContentTagAssignment上的FK,它是LinkId –

+1

正確。但是在OP提供的ContentTagAssignment實體中沒有'LinkId'屬性,並且根據OP的解釋,* LinkId將與ContentTagAssignment *中的ArticleId匹配,所以我的假設是基於該語句(並且在答案中提及)。 –

1

您的實體模型/實現有兩個問題。

讓我們從simlpler開始(在Gert Arnold's comment中提到)。作爲一個經驗法則,您不應該在構造函數(或其他內部任何地方)內初始化一個導航屬性,因爲這會破壞EF惰性加載行爲。

不久,只需刪除從ContentTagAssignment類的構造函數

this.ContentExternalLink = new ContentExternalLink();

線。

現在是主要問題。 EF6僅支持引用主體端PK(主鍵)的FK(外鍵)關係。這意味着您不能在ContentTagAssignment實體中使用組合鍵(TagId, ArticleId)來引用ContentExternalLink實體的單個PK(LinkId),因爲您試圖使用HasForeignKey(t => new {t.TagId, t.ArticleId})呼叫進行設置。這兩列構成了從屬關係的PK(ContentTagAssignment)這一事實與關係無關。沒有其他選擇 - 你必須選擇兩個領域之一。並且根據LinkId將匹配ContentTagAssignment中的ArticleId,這應該是ArticleId字段。

如果我的猜測是正確的,只需用

this.HasRequired(t => t.ContentExternalLink) 
    .WithMany(t => t.ContentTagAssignments) 
    .HasForeignKey(t => t.ArticleId); 

和(與構造函數修改沿)取代

this.HasOptional(t => t.ContentExternalLink) 
    .WithMany(t => t.ContentTagAssignments) 
    .HasForeignKey(t => new {t.TagId, t.ArticleId}); 

應該解決的問題。

請注意,我也改變HasOptionalHasRequired因爲ArticleId場是PK的一部分,因此不會允許null值反正。

0

我相信問題在於你試圖擁有一個沒有指明正確連接的外鍵。

你需要做的就是添加一個鏈路ID字段ContentTagAssignment這是你應該使用,並加入到實際的外鍵:

this.HasOptional(t => t.ContentExternalLink) 
.WithMany(t => t.ContentTagAssignments) 
.HasForeignKey(t => t.LinkId); 

的原因是,你告訴它去找到一個key(tagId,ArticleId)只是不存在於ContentExternalLink中。

相關問題