以下哪些实体属性最可能包含有效属性

数据库系统概论考试总复习题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
喜欢此文档的还喜欢
数据库系统概论考试总复习题
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢数据库期末考试复习题及答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
&&¥5.00
&&¥5.00
喜欢此文档的还喜欢
数据库期末考试复习题及答案
十​套​数​据​库​复​习​题​,​配​有​答​案​详​解​,​是​期​末​复​习​不​错​的​选​择​。
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢1您所在的位置: &
EF Code First:数据更新最佳实践(2)
EF Code First:数据更新最佳实践(2)
最近在整理EntityFramework数据更新的代码,颇有体会,觉得有分享的价值,于是记录下来,让需要的人少走些弯路也是好的。为方便起见,先创建一个控制台工程,使用using(var db = new DataContext)的形式来一步一步讲解EF数据更新的可能会遇到的问题及对应的解决方案。在获得最佳方案之后,再整合到本系列的代码中。
整体更新的最佳实现
综合上面的几种情景,我们可以得到EF对实体整体更新的最佳方案,这里写成DbContext的扩展方法,代码如下:
public&static&void&Update&TEntity&(this&DbContext&dbContext,&params&TEntity[]&entities)&where&TEntity&:&EntityBase &{ &&&&&if&(dbContext&==&null)&throw&new&ArgumentNullException(&dbContext&); &&&&&if&(entities&==&null)&throw&new&ArgumentNullException(&entities&); &&&&&&foreach&(TEntity&entity&in&entities) &&&&&{ &&&&&&&&&DbSet&TEntity&&dbSet&=&dbContext.Set&TEntity&(); &&&&&&&&&try&&&&&&&&&{ &&&&&&&&&&&&&DbEntityEntry&TEntity&&entry&=&dbContext.Entry(entity); &&&&&&&&&&&&&if&(entry.State&==&EntityState.Detached) &&&&&&&&&&&&&{ &&&&&&&&&&&&&&&&&dbSet.Attach(entity); &&&&&&&&&&&&&&&&&entry.State&=&EntityState.M &&&&&&&&&&&&&} &&&&&&&&&} &&&&&&&&&catch&(InvalidOperationException) &&&&&&&&&{ &&&&&&&&&&&&&TEntity&oldEntity&=&dbSet.Find(entity.Id); &&&&&&&&&&&&&dbContext.Entry(oldEntity).CurrentValues.SetValues(entity); &&&&&&&&&}& &&&&&} &}&
调用代码如下:
db.Update&Member&(member); &int&count&=&db.SaveChanges();&
针对不同的情景,将执行不同的行为:
情景一:上面代码第11行执行后entry.State将为EntityState.Modified,会直接退出此Update方法直接进入SaveChanges的执行。此情景执行的sql语句为只更新变更的实体属性。
情景二:将正确执行 try 代码块。此情景执行的sql语句为更新全部实体属性。
情景三:在代码执行到第12行的Attach方法时将抛出&InvalidOperationException 异常,接着执行 catch 代码块。此情景执行的sql语句为只更新变更的实体属性。&
三、按需更新(更新指定实体属性)
前面已经有整体更新了,很多时候也都能做到只更新变化的实体属性,为什么还要来个&按需更新&的需求呢?主要基于以下几点理由:
整体更新中获取数据的变更是要把新值与原始值的属性一一对比的,因而整体更新要从数据库中获取完整的实体数据,以保证被更新的只有我们想要改变的实体属性,这样进行整体更新时至少要从数据库中查询一次数据。
执行的更新语句有可能是更新所有实体属性的(如上的情景三),如果实体属性很多,就容易造成计算资源的浪费(因为我们只需要更新其中的某几个属性值)。
不能只更新指定的实体属性,有了按需更新,我们可以非常方便的只更新指定的属性,没有指定的属性即使值变化了也不更新
按需更新,也就是知道要更新的实体属性,比如用户要修改密码,就只是要把Password这个属性的值变更为指定的新值,其他的最好是尽量不惊动。当然,至少还是要知道要更新数据的主键的,否则,更新对象就不明了。下面就以设置密码为例来说明问题。
要设置密码,我构造了一个空的Member类来装载新密码:
Member&member&=&new&Member&{Id&=&1,&Password&=&&NewPassword&&+&DateTime.Now.Second};&
然后,我们想当然的写出了如下实现代码:
private&static&void&Method06() &{ &&&&&Member&member&=&new&Member&{Id&=&1,&Password&=&&NewPassword&&+&DateTime.Now.Second}; &&&&&using&(var&db&=&new&DataContext()) &&&&&{ &&&&&&&&&DbEntityEntry&Member&&entry&=&db.Entry(member); &&&&&&&&&entry.State&=&EntityState.U &&&&&&&&&entry.Property(&Password&).IsModified&=&true; &&&&&&&&&int&count&=&db.SaveChanges(); &&&&&&&&&Console.WriteLine(&操作结果:{0}&,&count&&&0&?&&更新成功。&&:&&未更新。&); &&&&&&&&&&Member&newMember&=&db.Members.Single(m&=&&m.Id&==&1); &&&&&&&&&Console.WriteLine(&更新后:{0}。&,&newMember.Password); &&&&&} &}&
然后,在执行第9行SaveChanges的时候引发了如下异常:
捕捉到&System.Data.Entity.Validation.DbEntityValidationException &&&HResult=- &&&Message=对一个或多个实体的验证失败。有关详细信息,请参见&EntityValidationErrors&属性。 &&&Source=EntityFramework&&&StackTrace: &&&&&&&&在&System.Data.Entity.Internal.InternalContext.SaveChanges() &&&&&&&&在&System.Data.Entity.Internal.LazyInternalContext.SaveChanges() &&&&&&&&在&System.Data.Entity.DbContext.SaveChanges() &&&&&&&&在&GmfEFUpdateDemo.Program.Method06()&位置&d:\Documents\Visual&Studio&2012\Projects\GmfEFUpdateDemo\GmfEFUpdateDemo\Program.cs:行号&224 &&&&&&&&在&GmfEFUpdateDemo.Program.Main(String[]&args)&位置&d:\Documents\Visual&Studio&2012\Projects\GmfEFUpdateDemo\GmfEFUpdateDemo\Program.cs:行号&63 &&&InnerException:&
为什么出现此异常?因为前面我们创建的Member对象只包含一个Id,一个Password属性,其他的属性并没有赋值,也不考虑是否规范,这样就定义出了一个不符合实体类验证定义的对象了(Member类要求UserName属性是不可为空的)。幸好,DbContext.Configuration中给我们定义了是否在保存时验证实体有效性(ValidateOnSaveEnabled)这个开关,我们只要在执行按需更新的保存时把验证闭,在保存成功后再开启即可,更改代码如下:
private&static&void&Method06() &{ &&&&&Member&member&=&new&Member&{Id&=&1,&Password&=&&NewPassword&&+&DateTime.Now.Second}; &&&&&using&(var&db&=&new&DataContext()) &&&&&{ &&&&&&&&&DbEntityEntry&Member&&entry&=&db.Entry(member); &&&&&&&&&entry.State&=&EntityState.U &&&&&&&&&entry.Property(&Password&).IsModified&=&true; &&&&&&&&&db.Configuration.ValidateOnSaveEnabled&=&false; &&&&&&&&&int&count&=&db.SaveChanges(); &&&&&&&&&db.Configuration.ValidateOnSaveEnabled&=&true; &&&&&&&&&Console.WriteLine(&操作结果:{0}&,&count&&&0&?&&更新成功。&&:&&未更新。&); &&&&&&&&&&Member&newMember&=&db.Members.Single(m&=&&m.Id&==&1); &&&&&&&&&Console.WriteLine(&更新后:{0}。&,&newMember.Password); &&&&&} &}&
与整体更新一样,理所当然的会出现当前上下文已经存在了相同主键的实体数据的情况,当然,根据之前的经验,也很容易的进行处理了:
private&static&void&Method07() &&&&&{ &&&&&&&&&Member&member&=&new&Member&{&Id&=&1,&Password&=&&NewPassword&&+&DateTime.Now.Second&}; &&&&&&&&&using&(var&db&=&new&DataContext()) &&&&&&&&&{ &&&&&&&&&&&&&&&&&&&&&&&&&&Member&oldMember&=&db.Members.Single(m&=&&m.Id&==&1); &&&&&&&&&&&&&Console.WriteLine(&更新前:{0}。&,&oldMember.AddDate); &&&&&&&&&&&&&&try&&&&&&&&&&&&&{ &&&&&&&&&&&&&&&&&DbEntityEntry&Member&&entry&=&db.Entry(member); &&&&&&&&&&&&&&&&&entry.State&=&EntityState.U &&&&&&&&&&&&&&&&&entry.Property(&Password&).IsModified&=&true; &&&&&&&&&&&&&} &&&&&&&&&&&&&catch&(InvalidOperationException) &&&&&&&&&&&&&{ &&&&&&&&&&&&&&&&&DbEntityEntry&Member&&entry&=&db.Entry(oldMember); &&&&&&&&&&&&&&&&&entry.CurrentValues.SetValues(member); &&&&&&&&&&&&&&&&&entry.State&=&EntityState.U &&&&&&&&&&&&&&&&&entry.Property(&Password&).IsModified&=&true; &&&&&&&&&&&&&} &&&&&&&&&&&&&db.Configuration.ValidateOnSaveEnabled&=&false; &&&&&&&&&&&&&int&count&=&db.SaveChanges(); &&&&&&&&&&&&&db.Configuration.ValidateOnSaveEnabled&=&true; &&&&&&&&&&&&&Console.WriteLine(&操作结果:{0}&,&count&&&0&?&&更新成功。&&:&&未更新。&); &&&&&&&&&&&&&&Member&newMember&=&db.Members.Single(m&=&&m.Id&==&1); &&&&&&&&&&&&&Console.WriteLine(&更新后:{0}。&,&newMember.Password); &&&&&&&&&} &&&&&}&
但是,上面的代码却无法正常工作,经过调试发现,当执行到第20行的时候,entry中跟踪的数据又变回oldMember了,经过一番EntityFramework源码搜索,终于找到了问题的出处(System.Data.Entity.Internal.InternalEntityEntry类中):
public&EntityState&State &&&&&{ &&&&&&&get&&&&&&&{ &&&&&&&&&if&(!this.IsDetached) &&&&&&&&&&&return&this._stateEntry.S &&&&&&&&&else&&&&&&&&&&&return&EntityState.D &&&&&&&} &&&&&&&set&&&&&&&{ &&&&&&&&&if&(!this.IsDetached) &&&&&&&&&{ &&&&&&&&&&&if&(this._stateEntry.State&==&EntityState.Modified&&&&value&==&EntityState.Unchanged) &&&&&&&&&&&&&this.CurrentValues.SetValues(this.OriginalValues); &&&&&&&&&&&this._stateEntry.ChangeState(value); &&&&&&&&&} &&&&&&&&&else&&&&&&&&&{ &&&&&&&&&&&switch&(value) &&&&&&&&&&&{ &&&&&&&&&&&&&case&EntityState.Unchanged: &&&&&&&&&&&&&&&this._internalContext.Set(this._entityType).InternalSet.Attach(this._entity); &&&&&&&&&&&&&&&break; &&&&&&&&&&&&&case&EntityState.Added: &&&&&&&&&&&&&&&this._internalContext.Set(this._entityType).InternalSet.Add(this._entity); &&&&&&&&&&&&&&&break; &&&&&&&&&&&&&case&EntityState.Deleted: &&&&&&&&&&&&&case&EntityState.Modified: &&&&&&&&&&&&&&&this._internalContext.Set(this._entityType).InternalSet.Attach(this._entity); &&&&&&&&&&&&&&&this._stateEntry&=&this._internalContext.GetStateEntry(this._entity); &&&&&&&&&&&&&&&this._stateEntry.ChangeState(value); &&&&&&&&&&&&&&&break; &&&&&&&&&&&} &&&&&&&&&} &&&&&&&} &&&&&}&
第14、15行,当状态由Modified更改为Unchanged的时候,又把数据重新设置为旧的数据OriginalValues了。真吭!
好吧,看来在DbContext中折腾已经没戏了,只要去它老祖宗ObjectContext中找找出路,更改实现如下:
private&static&void&Method08() &&&&&{ &&&&&&&&&Member&member&=&new&Member&{&Id&=&1,&Password&=&&NewPassword&&+&DateTime.Now.Second&}; &&&&&&&&&using&(var&db&=&new&DataContext()) &&&&&&&&&{ &&&&&&&&&&&&&&&&&&&&&&&&&&Member&oldMember&=&db.Members.Single(m&=&&m.Id&==&1); &&&&&&&&&&&&&Console.WriteLine(&更新前:{0}。&,&oldMember.AddDate); &&&&&&&&&&&&&&try&&&&&&&&&&&&&{ &&&&&&&&&&&&&&&&&DbEntityEntry&Member&&entry&=&db.Entry(member); &&&&&&&&&&&&&&&&&entry.State&=&EntityState.U &&&&&&&&&&&&&&&&&entry.Property(&Password&).IsModified&=&true; &&&&&&&&&&&&&} &&&&&&&&&&&&&catch&(InvalidOperationException) &&&&&&&&&&&&&{ &&&&&&&&&&&&&&&&&ObjectContext&objectContext&=&((IObjectContextAdapter)db).ObjectC &&&&&&&&&&&&&&&&&ObjectStateEntry&objectEntry&=&objectContext.ObjectStateManager.GetObjectStateEntry(oldMember); &&&&&&&&&&&&&&&&&objectEntry.ApplyCurrentValues(member); &&&&&&&&&&&&&&&&&objectEntry.ChangeState(EntityState.Unchanged); &&&&&&&&&&&&&&&&&objectEntry.SetModifiedProperty(&Password&); &&&&&&&&&&&&&} &&&&&&&&&&&&&db.Configuration.ValidateOnSaveEnabled&=&false; &&&&&&&&&&&&&int&count&=&db.SaveChanges(); &&&&&&&&&&&&&db.Configuration.ValidateOnSaveEnabled&=&true; &&&&&&&&&&&&&Console.WriteLine(&操作结果:{0}&,&count&&&0&?&&更新成功。&&:&&未更新。&); &&&&&&&&&&&&&&Member&newMember&=&db.Members.Single(m&=&&m.Id&==&1); &&&&&&&&&&&&&Console.WriteLine(&更新后:{0}。&,&newMember.Password); &&&&&&&&&} &&&&&}&
catch代码块使用了EF4.0时代使用的ObjectContext来实现,很好的达到了我们的目的,执行的sql语句如下:
exec&sp_executesql&N'update&[dbo].[Members] &set&[Password]&=&@0 &where&([Id]&=&@1) &',N'@0&nvarchar(50),@1&int',@0=N'NewPassword2',@1=1&
内容导航&第 1 页: &第 2 页: &第 3 页:
关于&&&&&&的更多文章
这个架构是从我近期在做的一个项目中剥离出来的,这个项目由我从
网友评论TOP5
本次的专刊为大家提供了Oracle最新推出的Java SE 8详细的开发教程,从解读到探究Java 8最新
讲师: 0人学习过讲师: 31人学习过讲师: 50人学习过
十一长假归来上班,好像更累了;早上也越来越堵了。小
数据结构课程,貌似是大学计算机、网络、软件等专业的
JavaScript正凭借新型工具与功能提升以极度夸张的速度
本书详细介绍脚本语言Groovy,首先介绍Groovy语言的基本特性,包括讨论Groovy方法、程序闭包、列表、映射以及对类和继承的支持,
51CTO旗下网站数据库答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
数据库答案
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢管理信息系统习题集含答案版 第四版_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
喜欢此文档的还喜欢
管理信息系统习题集含答案版 第四版
总​复​习​是​看​ ​保​证​能​过​!
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢

我要回帖

更多关于 税收实体法有哪些 的文章

 

随机推荐