EF 6主要密钥违规与多对多关系

时间:2013-12-09 08:25:39

标签: asp.net asp.net-mvc entity-framework

我是'实体框架'和'代码优先'世界的新手,所以请耐心等待。我有2个实体文章标签。标签中的 TagName 列必须是唯一的,因为它是密钥。在后续文章中使用现有标记时,我遇到了主键冲突问题。我的实体看起来如下

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为文章,标签和TagArticles关系创建3个表

这是保存文章的代码

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在创建标签之前先检查标签是否存在以避免重复?

2 个答案:

答案 0 :(得分: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连接表中正确创建关系。

答案 1 :(得分:0)

替换代码的以下行

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

}