首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将ModelBinders与存储在OwinContext中的DbContext结合使用?

如何将ModelBinders与存储在OwinContext中的DbContext结合使用?
EN

Stack Overflow用户
提问于 2014-09-21 04:00:17
回答 2查看 1.1K关注 0票数 3

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

代码语言:javascript
复制
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);
    }
}

而且效果很好。例如,在这里:

代码语言:javascript
复制
public ActionResult Edit(Person entity, int? id)
{
    if (entity == null && id.HasValue)
        throw new HttpException(404, "Person not found.");

    return View(person);
}

问题是当我试图将它保存到数据库中时:

代码语言:javascript
复制
// 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:附加'..Person‘类型的实体失败,因为相同类型的另一个实体已经具有相同的主键值。如果图形中的任何实体具有冲突的键值,则使用“附加”方法或将实体的状态设置为“未更改”或“修改”时,就会发生这种情况。这可能是因为一些实体是新的,还没有收到数据库生成的键值。在本例中,使用'Add‘方法或’Add‘实体状态来跟踪图形,然后根据情况将非新实体的状态设置为“未更改”或“修改”。

在控制器操作中运行此操作时,实体状态显示为Detached

代码语言:javascript
复制
DbContext.Entry(entity).State

为什么会发生这种事?我怎么才能修好它?难道就不能用粘合剂吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-25 03:21:42

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

代码语言:javascript
复制
    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环境中获取一个值,如果不存在,则返回默认值(T)”。

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

,您能在某个地方调用IOwinContext.Set<ApplicationDbContext>并传递一个新的DbContext,以便您对HttpContext.GetOwinContext().Get()的两个调用共享同一个实例吗?

票数 5
EN

Stack Overflow用户

发布于 2014-09-25 01:50:51

编辑时,将保存前修改的实体状态设置为。

代码语言:javascript
复制
DbContext.Entry(entity).State = EntityState.Modified; 

由于现在实体框架没有跟踪这个实体,所以在试图保存它之前,需要显式地指定这是一个修改过的实体。

另一种方法是从数据库中检索实体,以便实体框架跟踪它。然后,使用修改后的值更改它的值,当您这样做时,实体框架会注意到它,并将其设置为自动修改。然后,您可以保存更改。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25955652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档