“Post”类型上的“Tags”属性不是原始属性或复杂属性。 Property 方法只能与原始或复杂属性一起使用。使用参考或收集方法。
我正在使用此代码片段来更新帖子文本和相关标签:
var tags = TagConverter.FetchTags(postText);
var newTags = tags.Select(t => t.Title);
var savedTags = _db.Tags.Where(t => newTags.Contains(t.Title)).ToList();
var notSavedTags = tags.Where(t => savedTags.All(st => st.Title != t.Title)).ToList();
var insertedTags = _db.Tags.AddRange(notSavedTags).ToList();
insertedTags.AddRange(savedTags);
_db.SaveChanges();
var updatedPost = post;
updatedPost.Title = postText;
updatedPost.Tags = insertedTags;
_db.Posts.Attach(updatedPost);
var entry = _db.Entry(updatedPost);
entry.Property(e => e.Title).IsModified = true;
entry.Property(e => e.Tags).IsModified = true;
_db.SaveChanges();
如何更新标签?
设置
IsModified
适用于单个实体,不适用于集合。这就是为什么这条线不起作用:
entry.Property(e => e.Tags).IsModified = true;
由于您已经将所有标签附加到上下文,因此您需要手动将
updatedPost.Tags
集合与 insertedTags
进行比较和更新。
首先,我认为只需调用一次
_db.SaveChanges();
就可以正常工作。
由于这一行,您会收到异常,只需将其删除:
entry.Property(e => e.Tags).IsModified = true;
另外,我会放
_db.Posts.Attach(updatedPost);
之前updatedPost.Tags = insertedTags;
。
经过这些更改后,您的代码很可能应该可以工作。
另一种选择是使用 ChangeRelationshipState() 方法。看看下面的代码。您还可以查看此 EF 关系和导航属性文档 以获取更多信息(请参阅“创建和修改关系”部分)。
我只更改了代码的第二部分,还添加了“使用”:
using System.Data.Entity.Infrastructure;
var tags = TagConverter.FetchTags(postText);
var newTags = tags.Select(t => t.Title);
var savedTags = _db.Tags.Where(t => newTags.Contains(t.Title)).ToList();
var notSavedTags = tags.Where(t => savedTags.All(st => st.Title != t.Title)).ToList();
var insertedTags = _db.Tags.AddRange(notSavedTags).ToList();
insertedTags.AddRange(savedTags);
_db.SaveChanges();
var updatedPost = post();
_db.Posts.Attach(updatedPost);
updatedPost.Title = postText;
var entry = _db.Entry(updatedPost);
entry.Property(e => e.Title).IsModified = true;
foreach (var tag in insertedTags)
{
((IObjectContextAdapter)DbContext).ObjectContext.ObjectStateManager.
ChangeRelationshipState(updatedPost, tag, e => e.Tags, EntityState.Added);
}
_db.SaveChanges();
您遇到的错误“‘Post’类型上的属性‘Tags’不是原始或复杂属性。Property 方法只能与原始或复杂属性一起使用。请使用 Reference 或 Collection 方法”,表示您正在尝试更新导航属性(可能是实体的集合),就好像它是一个简单的字段一样。
在实体框架中,表示实体之间关系的导航属性(例如“标签”属性)需要与原始或复杂属性不同的方法。以下是如何修改代码以正确更新“标签”集合的方法:
加载现有帖子和标签:首先,您应该从数据库加载现有帖子及其当前标签。这可确保您正在使用实体的当前状态。
更新帖子信息:按照您已经执行的操作更新帖子的基本属性。
更新标签:
清除帖子中的当前标签。 将新标签添加到帖子中。 以下是如何修改代码的示例:
var tags = TagConverter.FetchTags(postText);
var newTags = tags.Select(t => t.Title);
var savedTags = _db.Tags.Where(t => newTags.Contains(t.Title)).ToList();
var notSavedTags = tags.Where(t => savedTags.All(st => st.Title != t.Title)).ToList();
var insertedTags = _db.Tags.AddRange(notSavedTags).ToList();
_db.SaveChanges();
// Load the post and its current tags
var updatedPost = _db.Posts.Include(p => p.Tags).Single(p => p.Id == post.Id);
// Update the post's title
updatedPost.Title = postText;
// Update the tags
updatedPost.Tags.Clear();
foreach (var tag in insertedTags.Concat(savedTags))
{
updatedPost.Tags.Add(tag);
}
// Mark the title as modified
_db.Entry(updatedPost).Property(e => e.Title).IsModified = true;
// Save the changes
_db.SaveChanges();