多对多关系插入不正确

时间:2017-09-01 08:19:48

标签: c# entity-framework entity-relationship

我的模型中有很多关系:

Tag.cs​​

public class Tag 
{
   // more properites ...

   // user relations with forgin key
   public User CreatedBy { get; set; }
   public Guid CreatedById { get; set; }

   // has many posts
   public ICollection<Post> Posts { get; set; }
}

这是Tag Canfiguration:

  HasRequired(o => o.CreatedBy)
          .WithMany(user => user.Tags)
          .HasForeignKey(tag => tag.CreatedById)
          .WillCascadeOnDelete(false);

Post.cs

 public class Post
 {
     public ICollocation<Tag> Tag { get; set; }
 }

和配置:

 HasMany(post => post.Tags)
          .WithMany(tag => tag.Posts)
          .MapToStoredProcedures();

这是插入Post with Multiple tags的插入操作代码:

    public async Task InsertAsync(CreatePost postDto)
    {
        using (var transaction = _uow.Database.BeginTransaction())
        {
            // map dto class to Post
            var post = _mapper.Map<Post>(postDto);

            // here split tag names in dto
            var postTgs = postDto.TagNames.Split(',');

            // i get tags that contains postTags names 
            var tags = await _tags.AsNoTracking().Where(x => postTgs.Contains(x.Name)).ToListAsync().ConfigureAwait(false);

            _posts.Add(post);

            await _uow.SaveAllChangesAsync().ConfigureAwait(false);

            // get added post for add tags
            var newPost = await _posts.Include(o => o.Tags).SingleAsync(x => x.Id == post.Id).ConfigureAwait(false);

            foreach (var tag in tags)
            {
                // here add tags
                newPost.Tags.Add(new Tag(){Name = tag.Name,CreatedById = tag.CreatedById});
            }

            await _uow.SaveAllChangesAsync().ConfigureAwait(false);
            transaction.Commit();
        }
    }

问题是在数据库中插入多个标签的插入标签。此操作在标记表中添加新标记,但我希望将 PostTags 添加到存储标记中,以便自动生成它。

  1. 我该如何解决这个问题?
  2. 为什么此操作会插入新标签?
  3. 我解决这个问题,看看其他文件和问题,但没有得到结果。我认为我必须在我的模型中创建 PostTags 来解决这个问题。

    注意:Tag与用户有一个外键。

1 个答案:

答案 0 :(得分:2)

  

为什么此操作会插入新标记?

因为您要添加使用Tag创建的new Tag { ... }个实例。由于它们未附加到DbContext,因此EF假定它们是新记录(而不仅仅是指向现有记录的新链接)。

  

我该如何解决这个问题?

确保Tag个实例已正确附加到DbContext,状态指示现有记录。

从您的代码中不太清楚,但_posts_tags来自DbSet的{​​{1}}来自DbContext你需要的是在获取包含postTags名称的标签时删除_uow,从而能够正确跟踪它们是否存在,然后在将帖子添加到上下文之前简单地将该列表指定为帖子标签,从而告诉EF添加链接:

AsNoTracking

请注意,在这种情况下,事务是多余的,因为var post.Tags = await _tags.Where(x => postTgs.Contains(x.Name)).ToListAsync().ConfigureAwait(false); _posts.Add(post); await _uow.SaveAllChangesAsync().ConfigureAwait(false); transaction.Commit(); 已经为您做到了。