2013-12-09 117 views
1

我是新來的'實體框架'和'代碼第一'的世界,所以忍受着我。我有2個實體文章標籤。 Tag中的TagName列必須是唯一的,因爲它是關鍵。在後續文章中使用現有標籤時,我遇到了主鍵違規問題。我的實體如下所示EF 6與多對多關係的主鍵違規

public class Article 
{ 
    public Article() 
    { 
    } 
    public int Id { get; set; } 
    [StringLength(100)] 
    [Required] 
    public string Title { get; set; } 
    [Required] 
    public string Body { get; set; } 
    public virtual List<Tag> Tags { get; set; } 

} 

public class Tag 
{ 
    public Tag() 
    { 
    } 
    public Tag(string tagName) 
    { 
     TagName = tagName; 
    } 
    [Key] 
    [StringLength(25)] 
    public string TagName { get; set; } 
    public virtual List<Article> Articles { get; set; } 

    public override string ToString() 
    { 
     return this.TagName; 
    } 
} 

EF創建文章,標籤3個表和TagArticles關係

這裏是我的代碼來保存文章

var editedTags = Request["Tags"]; 
if (!string.IsNullOrEmpty(editedTags)) 
{ 
    var tags = Regex.Split(editedTags, "\r\n"); 
    if (tags != null && tags.Length > 0) 
    { 
    foreach (var tag in tags) 
    { 
     article.Tags.Add(new Tag(tag)); 
    } 
    } 
} 
//db is my context 
db.Articles.Add(article); 
db.SaveChanges(); //Crashes here if the tag already exists 

除了從手動創建標籤開始,有沒有辦法告訴EF檢查標籤是否先存在b在創建它之前要避免重複?

+0

那麼你問** **添加一個新的標籤,所以它會嘗試。我會先查詢一個現有的標籤,如果它不存在,然後添加它。簡而言之:不,AFAIK你必須手動完成,它完全符合你的要求。 –

+0

我認爲'爲現有的標籤/文章'更新'(刪除/添加)'標籤 - 文章關係'可能還需要手動編碼。 – Kaf

+0

@Adriano,我希望有一些'EF魔術'。然後我會手動完成。 –

回答

1

找到了解決辦法。對於Tag類,我添加了一個int列Id,並將其作爲主鍵。然後我更新了數據庫以反映這些變化。那就是:

public class Tag 
{ 
    public Tag() 
    { 
    } 
    public Tag(string tagName) 
    { 
     TagName = tagName; 
    } 
    [Key] 
    public int Id { get; set; } 
    [Required] 
    [StringLength(25)] 
    public string TagName { get; set; } 
    public virtual List<Article> Articles { get; set; } 

    public override string ToString() 
    { 
     return this.TagName; 
    } 
} 

我增加了一個功能,增加了新的標籤文章

private Article ParseTags(Article article) 
{ 
    var strTags = Request["Tags"]; 
    if (!string.IsNullOrEmpty(strTags)) 
    { 
    var arrTags = Regex.Split(strTags, "\r\n"); 
    if (arrTags != null && arrTags.Length > 0) 
    { 
     foreach (var tagName in arrTags) 
     { 
     var tag = db.Tags.FirstOrDefault(t => t.TagName.ToLower() == tagName.ToLower()); 
     if (tag == null) 
      article.Tags.Add(new Tag(tagName)); 
     else 
      article.Tags.Add(tag); 
     } 
    } 
    } 
    return article; 
} 

最後Create行動

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include="Title,Body")] Article article) 
{ 
    if (ModelState.IsValid) 
    {    
    db.Articles.Add(ParseTags(article)); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
    } 
    return View(article); 
} 

現在僅創建新的標籤和現有的有不重複,關係在TagsArticles連接表中正確創建。

+0

這太瘋狂了,沒有更多的人沒有遇到這個問題。 – Thumper

0

Replce以下代碼

foreach (var tag in tags) 
    { 
     article.Tags.Add(new Tag(tag)); 
    } 

的符合

foreach (var tag in tags) 
{ 

Tag objTag = db.Tags.SingleOrDefault(c => c.TagName == tag); 

if (!(objTag != null && objTag.TagName == tag)) 
    objTag = new Tag(tag); 

article.Tags.Add(objTag); 

} 
+0

雖然這樣可以避免在向標記表中添加標記時出現'違反主鍵'錯誤,但它不會自動在標記和文章之間建立關係。我希望有辦法做到這一點,但我可能不得不手動添加標籤。 –