在实体框架中分离和附加对象时出错

发布于 2024-11-02 18:26:13 字数 1125 浏览 0 评论 0原文

我使用 NoTracking 获取对象,转换并操作它,将其发送到 asp.net mvc 视图。我取回编辑后的版本,调用存储库中的编辑方法,尝试附加它,它会引发以下错误:

ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法使用相同的键跟踪多个对象。

如何获取数据:

IQueryable<User> query = db.Users.AsNoTracking();

如何编辑数据:

    public User UpdateUser(User user, IEnumerable<Expression<Func<User, object>>> properties)
    {
            db.Users.Attach(user); //Error happens right here.
            foreach (var selector in properties)
            {
                string propertyName = Helpers.PropertyToString(selector.Body);
                db.Entry(user).Property(propertyName).IsModified = true;
            }
            db.SaveChanges();
            return user;
    }

当我使用 AsNoTracking 获取实体时,不应该将其分离吗我?即使它没有分离,整个 asp.net 生命周期也应该在重新提交数据时重新启动,这将使图表为空。

我在这里做错了什么?

我这样进行绑定:

DbContext db = new DbContext("ConnStringName");
Bind<IUserRepository>().To<SqlServerUserRepository>()
                .WithConstructorArgument("db", db);

I get the object, using NoTracking, convert and manipulate it, send it to an asp.net mvc view. I get back an edited version, call the edit method in my repository, try to Attach it, it throws the following error:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

How I get the data:

IQueryable<User> query = db.Users.AsNoTracking();

How I edit the data:

    public User UpdateUser(User user, IEnumerable<Expression<Func<User, object>>> properties)
    {
            db.Users.Attach(user); //Error happens right here.
            foreach (var selector in properties)
            {
                string propertyName = Helpers.PropertyToString(selector.Body);
                db.Entry(user).Property(propertyName).IsModified = true;
            }
            db.SaveChanges();
            return user;
    }

When I get the entities using AsNoTracking, shouldn't that detach the thing for me? Even if it didn't detach, the whole asp.net life cycle is supposed to be restarted on resubmitting the data, which would make the graph empty.

What am I doing wrong here?

I do my bindings like this:

DbContext db = new DbContext("ConnStringName");
Bind<IUserRepository>().To<SqlServerUserRepository>()
                .WithConstructorArgument("db", db);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

懵少女 2024-11-09 18:26:13

听起来您的数据库上下文创建一次,并且该实例实际上是单例。当您尝试附加 User 时,上下文检测到缓存中已存在该用户并失败。

我建议更改每个请求创建的上下文。使用 Ninject,您可以将其绑定,

Bind<YourDbContext>().ToMethod(context => CreateContext()).InRequestScope();

其中 YourDbContextdb 变量的类型,CreateContext() 是 global.ascx 中的方法。

更新

您确实创建了一次数据库上下文并将其存储为单例。不用担心,您可以设置绑定,因为

// DbContext db = new DbContext("ConnStringName");
Bind<DbContext>().ToMethod(context => new DbContext("ConnStringName")).InRequestScope();
Bind<IUserRepository>().To<SqlServerUserRepository>().InRequestScope();

这将为每个请求创建一个新的 DbCOntext,并防止附加时缓存的 User 与提交的 User 发生冲突。

Sounds like your db context is created once and that instance is effectively a singleton. When you attempt to attach the User, the context detects that it already has one in the cache and fails.

I recommend changing the context to be created per request. With Ninject, you can bind it with

Bind<YourDbContext>().ToMethod(context => CreateContext()).InRequestScope();

where YourDbContext is the type of the db variable and CreateContext() is the method in your global.ascx.

UPDATE

You are indeed creating your database context once and storing it as a singleton. No worries, you can set up your bindings as

// DbContext db = new DbContext("ConnStringName");
Bind<DbContext>().ToMethod(context => new DbContext("ConnStringName")).InRequestScope();
Bind<IUserRepository>().To<SqlServerUserRepository>().InRequestScope();

This will create a new DbCOntext for each Request and prevent the cached User from colliding with the submitted User when attaching.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文