在日常使用Entity Framework中,数据更新通常会用到。下面就简单封装了一个DBContext类

public partial class EFContext<T> : DbContext where T : class
{
public EFContext(): base("name=MyConnectionString")
{
} protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<EFContext<T>> (null);
modelBuilder.Configurations.Add(new MemberMap());
modelBuilder.Configurations.Add(new RoleMap());
base.OnModelCreating(modelBuilder);
} public DbSet<T> Table { get; set; } public IQueryable<T> GetList(Expression<Func<T,bool>> where)
{
return this.Table.Where(where);
} public void Update(T entity)
{
if (entity == null)
{
throw new ArgumentException("entity");
}
this.SaveChanges();
}
}

第一种更新方式,先通过Entity Framework从数据库中查找出一条记录(实体对象),然后修改实体对象的各个属性,最后调用Update方法

static void Main(string[] args)
{
EFContext<Member> memberContext = new EFContext<Member>();
var members = memberContext.GetList(m => true).ToList();
var model = members.Find(m => m.Id == ); //第一种更新方式
model.Name = "猪八戒";
model.Delete = false;
memberContext.Update(model);
Console.ReadKey();
}

运行程序前:

运行程序后:

上面的方式可以修改为下面方式,DbContext封装类中Update可以修改为如下的形式:

public void Update(T entity)
{
if (entity == null)
{
throw new ArgumentException("entity");
}
this.Table.Attach(entity);
this.Entry(entity).State = EntityState.Modified;
this.SaveChanges();
}
static void Main(string[] args)
{
EFContext<Member> memberContext = new EFContext<Member>();
var members = memberContext.GetList(m => true).ToList();
var model = members.Find(m => m.Id == ); //第一种更新方式
model.Name = "沙师弟";
model.Delete = true;
memberContext.Update(model);
Console.ReadKey();
}

运行前:

运行后:

第二种方式是new一个对象,这个对象各个属性赋值,主键Id与数据库某条已存在的记录的Id相同

static void Main(string[] args)
{
EFContext<Member> memberContext = new EFContext<Member>();
var members = memberContext.GetList(m => true).ToList();
//var model = members.Find(m => m.Id == 3); ////第一种更新方式
//model.Name = "沙师弟";
//model.Delete = true;
//memberContext.Update(model); //第二种方式
Member entity = new Member();
entity.Id = ;
entity.Name = "李小龙";
entity.Password = "lixiaolong";
entity.Delete = false;
entity.RoleId = ;
memberContext.Update(entity); Console.WriteLine("update complete.");
Console.ReadKey();
}

运行程序,会抛出异常。

附加类型“Core.Member”的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为。这可能是因为某些实体是新的并且尚未接收数据库生成的键值。在此情况下,使用 "Add" 方法或者 "Added" 实体状态跟踪该图形,然后将非新实体的状态相应设置为 "Unchanged" 或 "Modified"。

因为Attach的实体对象是通过new创建的,而不是通过Entity Framework从数据库中获取的,但实例的主键对应数据在数据库中存在,该实例而不存在于DBContext上下文中,尝试Attach会抛出异常。通过监视可以看到是未附加到DbContext中

修改Update方法如下:

public void Update(T entity)
{
if (entity == null)
{
throw new ArgumentException("entity");
}
if (this.Entry(entity).State == EntityState.Detached)
{
HandleDetached(entity);
}
this.Table.Attach(entity);
this.Entry(entity).State = EntityState.Modified;
this.SaveChanges();
} private bool HandleDetached(T entity)
{
var objectContext = ((IObjectContextAdapter)this).ObjectContext;
var entitySet = objectContext.CreateObjectSet<T>();
var entityKey = objectContext.CreateEntityKey(entitySet.EntitySet.Name, entity);
object foundSet;
bool exists = objectContext.TryGetObjectByKey(entityKey, out foundSet);
if (exists)
{
objectContext.Detach(foundSet); //从上下文中移除
}
return exists;
}

再次运行程序,没有问题

关于Entity Framework更新的几种方式以及可能遇到的问题(附加类型“Model”的实体失败,因为相同类型的其他实体已具有相同的主键值)在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为的更多相关文章

  1. 附加类型“UniversalReviewSystem.Models.ApplicationUser”的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值

    在使用asp.net Identity2 的 UserManager RoleManager 时,同时还有其他仓储类型接口,能实现用户扩展信息的修改,用户注册没有问题.当修改用户信息时,出现了如下异常 ...

  2. 附加类型的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值

    var list= DAL.LoadEntities(x => x.OrderCode == orderCode).AsNoTracking().ToList().FirstOrDefault( ...

  3. 因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 。。。

    因为相同类型的其他实体已具有相同的主键值.在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified&quo ...

  4. 错误:因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 解决方法

    在更新一个实体类的时候可能会有预先有一次查询或者其它操作,我们这样用目的是为了与提交的数据做一个比较之类的东西,如果先查询再对此类进行SaveChanges就会出错. 我们只要用AsNoTrackin ...

  5. 转:ASP.NET MVC + EF 更新的几种方式

    1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...

  6. ASP.NET MVC + EF 更新的几种方式(超赞)

    1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...

  7. ASP.NET MVC + EF 更新的几种方式

    1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...

  8. mysql级联更新的两种方式:触发器更新和外键

    1.mysql级联更新有两种方式:触发器更新和外键更新. 2.触发器更新和外键更新的目的都是为了保证数据完整性. 我们通常有这样的需求:删除表Table 1中记录,需要同时删除其它表中与Table 1 ...

  9. mysql批量更新的两种方式效率试验<二>

    Mysql两种批量更新的对比 简介: mysql搭载mybits框架批量更新有两种方式,一种是在xml中循环整个update语句,中间以‘:’隔开,还有一种是使用case when 变相实现批量更新, ...

随机推荐

  1. 《Mysql技术内幕,Innodb存储引擎》——事物

    事物 事物中的操作要么都成功要么都不做,这是事物的目的,也是事物模型与文件系统的重要特征之一. 扁平事物(Flat Transactions) 所有操作都处于同一层次,要么都做要么都执行要么都回滚,无 ...

  2. @Override 注解compiler1.5和compiler1.6不同

    说到注解问题,@interface 来定义注解类 这个注解出现是在jdk1.5版本出现. jdk1.5只支持@override对类的继承中方法重写的使用,不支持接口实现中方法重写的使用(这种情况下会报 ...

  3. centos7-windows10 双系统安装

    win10默认, 然后压缩出来一个卷安装win7: http://www.techweb.com.cn/network/system/2016-12-21/2456741.shtml http://b ...

  4. 15-hadoop-eclipse插件的安装

    好久没更新了, 也好久没学了, 今天换了个eclipse版本, 安装插件坑了一会, 果然好记性不如烂笔头, 记下来吧 编译安装或者直接安装都可以, 先说下编译安装吧 1, 编译安装, 是使用的ant, ...

  5. Node.js http服务器搭建和发送http的get、post请求

    1.Node.js 搭建http服务器 1.1创建server.js var http = require('http'); var querystring = require('querystrin ...

  6. 撩课-Web大前端每天5道面试题-Day18

    1.如何判断一个变量是对象还是数组? 判断数组和对象分别都有好几种方法,其中用prototype.toString.call()兼容性最好. function isObjArr(variable){ ...

  7. DOS窗口带jar包运行java程序

    由于工作环境的问题,有过一次这样的测试,需要在DOS窗口运行带有jar包的java程序 编译命令如下: javac -Djava.ext.dirs=./lib Test.java 或 javac -D ...

  8. Java springmvc 统一异常处理的方案

    前言:为什么要统一异常处理?经常在项目中需要统一处理异常,将异常封装转给前端.也有时需要在项目中统一处理异常后,记录异常日志,做一下统一处理. Springmvc 异常统一处理的方式有三种. 一.使用 ...

  9. AutoFac使用方法总结一:注册

    AutoFac是.net平台下的IOC容器产品,它可以管理类之间的复杂的依赖关系.在使用方面主要是register和resolve两类操作. 这篇文章用单元测试的形式列举了AutoFac的常用使用方法 ...

  10. future3.2 Tomcat启动时错误:Cannot rename original file to ...

    其日志中第一个警告如下: 警告: Unexpected exception resolving reference java.io.IOException: Cannot rename origina ...