0

我正在尝试实现与我们在 SO - 标记系统上的功能非常相似的功能。我输入标签,它会查看它们是否存在 - 如果不存在,则会通过连接表(多对多)创建与帖子相关联的标签。

它的工作原理如下:用户在“,”-分隔值(TagList)中输入标签。我用 RegEx 拆分 TagList 以提取不同的标签 - 我尝试在数据库中查找标签。如果它不存在,我创建它。

到目前为止,这就是我所拥有的:

食谱.cs

public class Recipe
{
    [Key]
    public int RecipeId { get; set; }
    [Required]
    public string Name { get; set; }
    public string Subtitle { get; set; }
    public int Serving { get; set; }
    public string Instructions { get; set; }
    public int PrepTime { get; set;}
    public int CookingTime { get; set; }
    public IList<Wine> Wines { get; set; }
    public IList<Pairing> Pairings { get; set; } 
    public ICollection<UsedIngredient> UsedIngredients { get; set; }

    [NotMapped]
    public string TagList { get; set; }
    public IList<Tag> Tags { get; set; } 
}

标签.cs

public class Tag
{
    public int TagId { get; set; }
    public string Name { get; set; }
    public ICollection<Recipe> Recipes { get; set; }      
}

连接表

创建表(

"dbo.TagRecipes",
        c => new
            {
                Tag_TagId = c.Int(nullable: false),
                Recipe_RecipeId = c.Int(nullable: false),
            })
        .PrimaryKey(t => new { t.Tag_TagId, t.Recipe_RecipeId })
        .ForeignKey("dbo.Tags", t => t.Tag_TagId, cascadeDelete: true)
        .ForeignKey("dbo.Recipes", t => t.Recipe_RecipeId, cascadeDelete: true)
        .Index(t => t.Tag_TagId)
        .Index(t => t.Recipe_RecipeId);

TagRepo - FindOrCreate 方法

public Tag FindOrCreateTag(string tagName)
{
    Tag tag = context.Tags.Where(t => t.Name == tagName).Include("Recipes").FirstOrDefault();
    if (tag == null)
    {
         tag = new Tag
         {
             Name = tagName,
             Recipes = new List<Recipe>()                        
          };
          context.Tags.Add(tag);
     }           
    return tag;
}

RecipeRepo - GetTagList

private IList<String> GetTagList(string tagString)
{
    IList<string> tagList = new List<string>(Regex.Split(tagString, @"\,\s*"));
    return tagList;
}

RecipeRepo - 分配标签

public void AssignTags(Recipe recipe, string tagString)
{
    if (recipe.Tags == null)
        recipe.Tags = new List<Tag>();
    IList<string> tags = GetTagList(tagString);
    foreach (string tagName in tags)
    {
        Tag tag = tagRepository.FindOrCreateTag(tagName);
        if (tag.Recipes == null)
           tag.Recipes = new List<Recipe>();
        if (!tag.Recipes.Any(r => r.RecipeId == recipe.RecipeId))
           tag.Recipes.Add(recipe);
        if (recipe.Tags.All(t => t.TagId != tag.TagId))
           recipe.Tags.Add(tag);
     }   
}

最后,我打电话给这个。

RecipeRepo - 更新

public bool Update(Recipe recipe)
{
    if (recipe.TagList != null)
        AssignTags(recipe, recipe.TagList);

     Recipe dbEnt = context.Recipes.Find(recipe.RecipeId);
     context.Entry(dbEnt).CurrentValues.SetValues(recipe);

     return Save();
}

发生的事情是 - 它需要字符串,正确地拆分它 - 但在那之后,事情似乎有点南下。它不是简单地分配新标签,而是复制配方对象。

是什么,我失踪了?

4

1 回答 1

0

从上下文中检索的对象(例如 的结果Find)应该在具有更改跟踪功能之前“附加”,并且可以在数据库中更新。
您还应该将其标记为“已修改”。

例如,正确的更新方法应该是这样的:

public bool Update(Recipe recipe)
{
    if (recipe.TagList != null)
        AssignTags(recipe, recipe.TagList);

     Recipe dbEnt = context.Recipes.Find(recipe.RecipeId);

     if (context.Entry(dbEnt).State == EntityState.Detached)
     {
         context.Set<Recipe>().Attach(dbEnt);
     }
     context.Entry(dbEnt).State = EntityState.Modified;

     context.Entry(dbEnt).CurrentValues.SetValues(recipe);

     return Save();
}

如果你想做一个通用的更新函数,它应该如下所示:

public void Update(TEntity entityToUpdate)
{
    if (context.Entry(entityToUpdate).State == EntityState.Detached)
    {
        context.Set<TEntity>().Attach(entityToUpdate);
    }
    context.Entry(entityToUpdate).State = EntityState.Modified;
}
于 2013-07-24T17:25:53.630 回答