我得到对象,使用NoTracking,转换和操作它,将它发送到asp.net mvc视图。我得到一个编辑过的版本,在我的存储库中调用edit方法,尝试附加它,它抛出以下错误:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
如何获取数据:
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);
听起来你的数据库上下文是创建一次,该实例是有效的单例。当您尝试附加User
时,上下文检测到它已经在缓存中有一个并且失败。
我建议更改要为每个请求创建的上下文。使用Ninject,你可以用
绑定它Bind<YourDbContext>().ToMethod(context => CreateContext()).InRequestScope();
其中YourDbContext
是db
变量的类型,CreateContext()
是您的global.ascx中的方法。
您确实创建了数据库上下文一次,并将其作为单例存储。不用担心,您可以将绑定设置为
// DbContext db = new DbContext("ConnStringName");
Bind<DbContext>().ToMethod(context => new DbContext("ConnStringName")).InRequestScope();
Bind<IUserRepository>().To<SqlServerUserRepository>().InRequestScope();
这将为每个请求创建一个新的DbCOntext,并防止在附加时缓存的User
与提交的User
冲突。