关于Entity Framework更新的几种方式以及可能遇到的问题(附加类型“Model”的实体失败,因为相同类型的其他实体已具有相同的主键值)在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为
在日常使用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" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为的更多相关文章
- 附加类型“UniversalReviewSystem.Models.ApplicationUser”的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值
在使用asp.net Identity2 的 UserManager RoleManager 时,同时还有其他仓储类型接口,能实现用户扩展信息的修改,用户注册没有问题.当修改用户信息时,出现了如下异常 ...
- 附加类型的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值
var list= DAL.LoadEntities(x => x.OrderCode == orderCode).AsNoTracking().ToList().FirstOrDefault( ...
- 因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 。。。
因为相同类型的其他实体已具有相同的主键值.在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified&quo ...
- 错误:因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 解决方法
在更新一个实体类的时候可能会有预先有一次查询或者其它操作,我们这样用目的是为了与提交的数据做一个比较之类的东西,如果先查询再对此类进行SaveChanges就会出错. 我们只要用AsNoTrackin ...
- 转:ASP.NET MVC + EF 更新的几种方式
1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...
- ASP.NET MVC + EF 更新的几种方式(超赞)
1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...
- ASP.NET MVC + EF 更新的几种方式
1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...
- mysql级联更新的两种方式:触发器更新和外键
1.mysql级联更新有两种方式:触发器更新和外键更新. 2.触发器更新和外键更新的目的都是为了保证数据完整性. 我们通常有这样的需求:删除表Table 1中记录,需要同时删除其它表中与Table 1 ...
- mysql批量更新的两种方式效率试验<二>
Mysql两种批量更新的对比 简介: mysql搭载mybits框架批量更新有两种方式,一种是在xml中循环整个update语句,中间以‘:’隔开,还有一种是使用case when 变相实现批量更新, ...
随机推荐
- win7使用命令
osk 屏幕键盘 perfmon 性能监视器 PresentationSettings 演示设置 recdisc.exe 创建系统恢复光盘 regedt32 注册表编辑器 rekeywiz 加密文件系 ...
- JavaScript -- 运算符、eval、Parse
----- 003-运算符.html ----- <!DOCTYPE html> <html> <head> <meta http-equiv="C ...
- kendo UI 入门
Kendo UI 是一套前端开发宽假,意为日本的“剑道” 首先到官方网站下载最新的30天试用版,地址为:http://www.telerik.com/download/kendo-ui 需要简单注册一 ...
- Eclipse安装fat jar的两种方式
help >software updates >add/remove software>add>>add site填写name 和urlname:Fat Jarurl:h ...
- css揭秘
一:渐变 线性渐变(Linear Gradients)- 向下/向上/向左/向右/对角方向 background: linear-gradient(direction, color-sto ...
- [转载]常见的移动端H5页面开发遇到的坑和解决办法
转过来,平时看看.虽然还有很多问题至今无解.比如:华为麒麟950的P8和meta打开我们的应用首页经常偶发白屏.!! 1.安卓浏览器看背景图片,有些设备会模糊. 用同等比例的图片在PC机上很清楚,但是 ...
- JS中的编码,解码类型及说明
使用ajax向后台提交的时候 由于参数中含有# 默认会被截断 只保留#之前的字符 json格式的字符串则不会被请求到后台的action 可以使用encodeURIComponent在前台进行编码, ...
- Angular的表单组件
创建表单元素 在上一节中,我们学习了如何创建一个组件login,现在将login改造一下, 在template中添加html表单元素,#usernameRef表示input元素id,如果想传递inpu ...
- jquery源码学习笔记(一)jQuery的无new构建
本人是一名.net程序员..... 你一个.net coder 看什么jQuery 源码啊? 原因吗,很简单.技多不压身吗(麻蛋,前端工作好高...羡慕). 我一直都很喜欢JavaScript,废话不 ...
- [PHP] 重回基础(IO流)
IO流用来处理设备之间的数据传输 java对数据的操作是通过流的方式 java用于操作流的对象都在IO包中 流按操作数据分为两种:字节流与字符流 流按流向分为:输入流,输出流 字符流 抽象基类:Rea ...