其他分享
首页 > 其他分享> > CodeGo.net>如何将ModelBinders与存储在OwinContext中的DbContext一起使用?

CodeGo.net>如何将ModelBinders与存储在OwinContext中的DbContext一起使用?

作者:互联网

我有一个简单的模型活页夹:

public class PersonBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // ...
        // id = routevalues[ id ]

        var db = controllerContext.HttpContext.GetOwinContext().Get<ApplicationDbContext>();

        return db.Set<Person>().FirstOrDefault(o => o.Id == id);
    }
}

而且效果很好.例如:

public ActionResult Edit(Person entity, int? id)
{
    if (entity == null && id.HasValue)
        throw new HttpException(404, "Person not found.");

    return View(person);
}

问题是当我尝试将其保存在数据库中时:

// DbContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>()

[HttpPost]
public async Task<ActionResult> Edit(Person entity, int? id)
{
    if (entity == null && id.HasValue)
        throw new HttpException(404, "Person not found.");

    if (ModelState.IsValid)
    {

        // WORKS when inserting a new person to the database
        if (!id.HasValue)
            DbContext.People.Add(entity);
        else
        {
            // if I try to attach I get an error: see bellow
            // if I don't attach, it does nothing
        }

        await DbContext.SaveChangesAsync();
    }

    return View(entity);
}

附加错误:

System.InvalidOperationException: Attaching an entity of type ‘..Person’ failed because another entity of the same type already has the same primary key value. This can happen when using the ‘Attach’ method or setting the state of an entity to ‘Unchanged’ or ‘Modified’ if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the ‘Add’ method or the ‘Added’ entity state to track the graph and then set the state of non-new entities to ‘Unchanged’ or ‘Modified’ as appropriate.

在控制器操作中运行时,实体状态显示为“已分离”:

DbContext.Entry(entity).State

为什么会发生?我该如何解决?不能为此使用粘合剂吗?

解决方法:

在执行附加之前,如果分离现有实体该怎么办?诸如此类:(未测试-抱歉,这是基于旧项目中的某些代码,出于不同的原因,我们不得不做类似的事情,但希望能给出想法)

    if (!id.HasValue)
        DbContext.People.Add(entity);
    else
    {
        var attachedEntity = DbContext.People.Find(id);
        if (attachedEntity != null && DbContext.Entry(attachedEntity).State != EntityState.Detached)
        {
            DbContext.Entry(attachedEntity).State = EntityState.Detached;
            // You may need to recursively detach child entities here if any
        }
        DbContext.People.Attach(entity);
        DbContext.Entry(entity).State = EntityState.Modified; 
    }

编辑:

由于主要问题似乎是您的DbContext的实例不同,因此有理由相信IOwinContext.Get< T>说:“从OWIN环境获取值,或者如果不存在,则返回default(T).”

http://msdn.microsoft.com/en-us/library/dn270607(v=vs.113).aspx

,您可以在某个地方(我没有使用OWIN太多,所以不确定最好的位置在哪里-但我想您可能会在管道的开头)致电IOwinContext.Set< ApplicationDbContext>并将新的DbContext传递给它,以便您对HttpContext.GetOwinContext().Get()的2个调用共享同一个实例?

标签:owin,asp-net-mvc-5,c,asp-net-mvc,entity-framework
来源: https://codeday.me/bug/20191029/1957634.html