c# - 如何将 ModelBinders 与存储在 OwinContext 中的 DbContext 一起使用?

标签 c# asp.net-mvc entity-framework asp.net-mvc-5 owin

我有一个简单的模型 Binder :

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.

当我在 Controller 操作中运行它时,实体状态显示为 Detached:

DbContext.Entry(entity).State

为什么会这样?我该如何解决?不能为此使用 Binder 吗?

最佳答案

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

    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

,你能不能在某个地方(我没有经常使用 OWIN,所以不确定最好的地方在哪里 - 但我猜在你的管道的开头)调用 IOwinContext.Set<ApplicationDbContext>并向其传递一个新的 DbContext,以便您对 HttpContext.GetOwinContext().Get() 的 2 个调用共享同一个实例?

关于c# - 如何将 ModelBinders 与存储在 OwinContext 中的 DbContext 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25955652/

相关文章:

jquery - ckeditor jquery 集成

c# - 在 MVVM (WPF) 应用程序中更改 ListView 上的筛选器后如何滚动到 View ?

c# - 将文本文件中的数据解析为数组

c# - 如何在用户注册期间生成 OWIN 不记名 token

entity-framework - Entity Framework 兼容 POCO 的最短语法

entity-framework - 更新 ef 中的实体

asp.net-mvc - MVC 2 和 Entity Framework - 我应该将实体类放在单独的层中吗?

c# - 如何从另一个项目添加对共享代码项目 (.shproj) 的引用

c# - 在 Visual C# 的 TreeView 控件中列出父节点的所有子节点

.Net Twitter OAuth 如何执行成功的 GET 请求