多对多关系插入不正确
Many To Many Relation Insert is not correct
我的模型中有多对多关系:
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; }
}
这里是标签配置:
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的插入操作代码:
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();
}
}
问题是插入 post 标签,它在数据库中插入了多个标签。此操作在 Tag table 中添加新标签,但我想将现有标签添加到 Ef 自动生成的 PostTags .
- 我该如何解决这个问题?
- 为什么这个操作插入新标签?
为了解决这个问题,我查看了其他文档和问题,但没有得到 result.I 认为我必须在我的模型中创建 PostTags为了解决这个问题。
注意:标签与用户有外键。
why this operation insert new tag?
因为您正在添加使用 new Tag { ... }
创建的 Tag
个实例。由于它们未附加到 DbContext
,因此 EF 假定它们是新记录(而不仅仅是现有记录的新链接)。
how can I solve this?
确保 Tag
实例正确附加到 DbContext
,状态指示现有记录。
从你的代码中看不太清楚,但是如果 _posts
和 _tags
是来自 _uow
使用的相同 DbContext
的 DbSet
,您所需要做的就是在获取包含 post 标签名称的标签时删除 AsNoTracking
,从而能够将它们正确地跟踪为现有标签,然后只需将该列表分配为 post 标签,然后再添加 post 到上下文,从而告诉 EF 添加链接:
var post.Tags = await _tags.Where(x => postTgs.Contains(x.Name)).ToListAsync().ConfigureAwait(false);
_posts.Add(post);
await _uow.SaveAllChangesAsync().ConfigureAwait(false);
transaction.Commit();
请注意,在这种情况下交易是多余的,因为 SaveChanges
已经为您完成了。
我的模型中有多对多关系:
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; }
}
这里是标签配置:
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的插入操作代码:
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();
}
}
问题是插入 post 标签,它在数据库中插入了多个标签。此操作在 Tag table 中添加新标签,但我想将现有标签添加到 Ef 自动生成的 PostTags .
- 我该如何解决这个问题?
- 为什么这个操作插入新标签?
为了解决这个问题,我查看了其他文档和问题,但没有得到 result.I 认为我必须在我的模型中创建 PostTags为了解决这个问题。
注意:标签与用户有外键。
why this operation insert new tag?
因为您正在添加使用 new Tag { ... }
创建的 Tag
个实例。由于它们未附加到 DbContext
,因此 EF 假定它们是新记录(而不仅仅是现有记录的新链接)。
how can I solve this?
确保 Tag
实例正确附加到 DbContext
,状态指示现有记录。
从你的代码中看不太清楚,但是如果 _posts
和 _tags
是来自 _uow
使用的相同 DbContext
的 DbSet
,您所需要做的就是在获取包含 post 标签名称的标签时删除 AsNoTracking
,从而能够将它们正确地跟踪为现有标签,然后只需将该列表分配为 post 标签,然后再添加 post 到上下文,从而告诉 EF 添加链接:
var post.Tags = await _tags.Where(x => postTgs.Contains(x.Name)).ToListAsync().ConfigureAwait(false);
_posts.Add(post);
await _uow.SaveAllChangesAsync().ConfigureAwait(false);
transaction.Commit();
请注意,在这种情况下交易是多余的,因为 SaveChanges
已经为您完成了。