C# 无法修改存储库中的对象

C# 无法修改存储库中的对象,c#,asp.net-mvc,entity-framework,repository-pattern,C#,Asp.net Mvc,Entity Framework,Repository Pattern,在ASP.NETMVC项目中,我尝试使用存储库中的方法SaveItem进行更新。我使用实体框架6.1。我有个例外。我怎样才能解决这个问题 附加“Domain.Entities.Post”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪

在ASP.NETMVC项目中,我尝试使用存储库中的方法SaveItem进行更新。我使用实体框架6.1。我有个例外。我怎样才能解决这个问题

附加“Domain.Entities.Post”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”

我的存储库:

public class BlogRepository<T> : IBlogRepository<T> where T : class
{
    private readonly DbContext context;
    private readonly IDbSet<T> dbSet;
    public BlogRepository()
    {
        this.context = new BlogDbContext();
        dbSet = context.Set<T>();
    }

    public BlogRepository(DbContext context, IDbSet<T> dbSet)
    {
        this.context = context;
        this.dbSet = dbSet;
    }

    public void SaveItem(T item)
    {
        object value = Reflector.GetPropertyValue(item);
        var foundItem = dbSet.Find((int) value);
        if (foundItem == default(T))
            dbSet.Add(item);
        else
        {
            context.Entry(item).State = EntityState.Modified;
        }
        context.SaveChanges();
    }

    public void Delete(T item)
    {
        dbSet.Remove(item);
        context.SaveChanges();
    }

    public T GetById(int id)
    {
        return dbSet.Find(id);
    }

    public IEnumerable<T> GetAll()
    {
        return dbSet.AsEnumerable();
    }
}
公共类BlogRepository:IBlogRepository其中T:class
{
私有只读DbContext上下文;
专用只读IDbSet数据库集;
公共博客存储库()
{
this.context=new BlogDbContext();
dbSet=context.Set();
}
公共BlogRepository(DbContext上下文,IDbSet dbSet)
{
this.context=上下文;
this.dbSet=dbSet;
}
公共作废保存项(T项)
{
对象值=Reflector.GetPropertyValue(项);
var foundItem=dbSet.Find((int)值);
如果(foundItem==默认值(T))
添加(项目);
其他的
{
context.Entry(item).State=EntityState.Modified;
}
SaveChanges();
}
公共作废删除(T项)
{
dbSet.移除(项目);
SaveChanges();
}
公共T GetById(int-id)
{
返回dbSet.Find(id);
}
公共IEnumerable GetAll()
{
返回dbSet.AsEnumerable();
}
}
在控制器中,我改进了编辑逻辑

 public class PostController : Controller  
 {
    private readonly IBlogRepository<Post> blogRepository;
    public PostController(IBlogRepository<Post> blogRepository)
    {
        this.blogRepository = blogRepository;
    }

    public ActionResult Index(int id = 1)
    {
        Post post = blogRepository.GetById(id);
        return View(post);
    }

    public ActionResult Edit(int id)
    {
        Post post = blogRepository.GetById(id);
        return View(post);
    }

    [HttpPost]
    public ActionResult Edit(Post post)
    {
        if (ModelState.IsValid)
        {
              blogRepository.SaveItem(post);
              return RedirectToAction("Index", new { id = post.Id });
        }

        return View(post);
    }

    public ActionResult Create()
    {
        return View("Edit", new Post {Date = DateTime.Now});
    }

}
公共类后控制器:控制器
{
私有只读IBlogRepository blogRepository;
公共邮政控制器(IBlogRepository blogRepository)
{
this.blogRepository=blogRepository;
}
公共行动结果索引(int id=1)
{
Post Post=blogRepository.GetById(id);
返回视图(post);
}
公共操作结果编辑(int id)
{
Post Post=blogRepository.GetById(id);
返回视图(post);
}
[HttpPost]
公共行动结果编辑(发布)
{
if(ModelState.IsValid)
{
blogRepository.SaveItem(post);
返回RedirectToAction(“Index”,new{id=post.id});
}
返回视图(post);
}
公共操作结果创建()
{
返回视图(“编辑”,新帖子{Date=DateTime.Now});
}
}

错误消息显示:

“如果图中的任何实体都有冲突的键值”

可能您的帖子是一个新元素,但数据库中已经存在相关元素(Author?)。然后,在添加帖子之前,您还必须“附加”这些项目


顺便说一下,我认为最好不要直接使用实体类作为视图的模型

最好使用一些“PostViewModel”类来公开必须显示的信息,也可以使用带有编辑数据的单独的“EditPostViewModel”。
您的控制器应该构造此类并将其发送到视图,还应该创建Post实体并将其发送到存储库(最好在服务类中完成)。

您是否尝试过在带有断点的调试模式下运行以查看发生了什么情况?是的,我尝试过,它引发了异常,然后您的变量值是什么,您是否使用了一些QuickWatch或其他工具来查看引擎盖下发生的情况?您可能会看到我的答案。类似于“db.Authors.Attach(post.Author);”?contect.DbSet.Attach(item)我这样做了,但它引发了相同的例外情况。如果您的post实体具有其他实体作为属性,例如post.Author,则必须附加此属性(当然,到他的自动数据库)