我想知道实体框架是否自动跟踪实体的导航属性的更改,并在使用SaveChanges()更新相关实体时更新这些更改。我正在使用通用存储库,工作单元,ninject与MVC 4中的代码第一实体框架5.我有一个具有多对多关系的帖子和标签表。我有一个这种关系的连接表,名为PostTagMap,有两列,Post_id和Tag_id。当我添加一个带有相关标签的新帖子时,新帖子已成功添加到帖子表中,PostTagMap也会保存与此帖子关联的标签。但是,当我尝试编辑/更新帖子及其相关标签时,只会更新帖子的标量属性,而不会更新相关标签。我尝试调试,我发现要更新的post实体确实具有标签导航属性的更新值,但实体框架只生成post表的更新语句而不是PostTagMap。我该怎么做才能更新帖子的标签导航属性。
以下是使用的课程
DBContext类
public class EFDbContext : DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasMany<Tag>(p => p.Tags)
.WithMany(u => u.Posts)
.Map(m =>
{
m.ToTable("PostTagMap");
m.MapLeftKey("Post_id");
m.MapRightKey("Tag_id");
});
}
}
发布课程
[Table("Post")]
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
标记类
[Table("Tag")]
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public ICollection<Post> Posts { get; set; }
}
实现IGenericRepository的通用存储库
public class EFGenericRepository<T> : IGenericRepository<T> where T : class
{
private DbContext DbContext { get; set; }
private DbSet<T> DbSet { get; set; }
public virtual void Add(T newEntity)
{
DbSet.Add(newEntity);
}
public virtual void Update(T entityToUpdate)
{
DbSet.Attach(entityToUpdate);
DbContext.Entry(entityToUpdate).State = EntityState.Modified;
}
}
实施IUnitOfWork的工作单元
public class EfUnitOfWork : IUnitOfWork
{
private EFDbContext dbContext;
private IGenericRepository<Post> postRepository;
private IGenericRepository<Tag> tagRepository;
public EfUnitOfWork()
{
this.dbContext = new EFDbContext();
}
public void Commit()
{
dbContext.SaveChanges();
}
public IGenericRepository<Post> PostRepository
{
get
{
if (this.postRepository == null)
{
this.postRepository = new EFGenericRepository<Post>(dbContext);
}
return postRepository;
}
}
public IGenericRepository<Tag> TagRepository
{
get
{
if (this.tagRepository == null)
{
this.tagRepository = new EFGenericRepository<Tag>(dbContext);
}
return tagRepository;
}
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
dbContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
服务层
public class ServiceRepository : IServiceRepository
{
private readonly IUnitOfWork UoW;
public ServiceRepository(IUnitOfWork _UoW)
{
UoW = _UoW;
}
public int AddPost(Post post)
{
UoW.PostRepository.Add(post);
UoW.Commit();
return post.Id;
}
public void EditPost(Post post)
{
UoW.PostRepository.Update(post);
UoW.Commit();
}
}
管理员控制器
public class AdminController : Controller
{
private readonly IServiceRepository _serviceRepository;
public AdminController(IServiceRepository serviceRepository)
{
_serviceRepository = serviceRepository;
}
[HttpPost, ValidateInput(false)]
public ContentResult AddPost(Post post)
{
string json;
ModelState.Clear();
if (TryValidateModel(post))
{
var id = _serviceRepository.AddPost(post);
json = JsonConvert.SerializeObject(new
{
id = id,
success = true,
message = "Post added successfully"
});
}
else
{
json = JsonConvert.SerializeObject(new
{
id = 0,
success = false,
message = "Post was not created"
});
}
return Content(json, "application/json");
}
[HttpPost, ValidateInput(false)]
public ContentResult EditPost(Post post)
{
string json;
ModelState.Clear();
if (TryValidateModel(post))
{
_serviceRepository.EditPost(post, Tags);
json = JsonConvert.SerializeObject(new
{
id = post.Id,
success = true,
message = "Post updated successfully"
});
}
else
{
json = JsonConvert.SerializeObject(new
{
id = 0,
success = false,
message = "Failed to save the changes."
});
}
return Content(json, "application/json");
}
}
我也在使用Post的自定义模型绑定器,如下所示
public class PostModelBinder : DefaultModelBinder
{
private readonly IKernel _kernel;
public PostModelBinder(IKernel kernel)
{
_kernel = kernel;
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var post = (Post)base.BindModel(controllerContext, bindingContext);
var _blogRepository = _kernel.Get<IServiceRepository>();
}
var tags = bindingContext.ValueProvider.GetValue("Tags").AttemptedValue.Split(',');
if (tags.Length > 0)
{
post.Tags = new List<Tag>();
foreach (var tag in tags)
{
post.Tags.Add(_serviceRepository.Tag( int.Parse(tag.Trim()) ));
}
}
return post;
}