我自己的一生

是你的,是我的,到底是谁的?

导航

Entity Framework 编程

 作者:Julia Lerman

译者:Abbott zhao

第五章 修改实体和保存变化

 

 

5.2  SaveChanges方法

ObjectContext有一个方法SaveChanges,负责把对实体所造成的修改持久化到后边数据库。调用SaveChanges方法,会检查被上下文环境管理的ObjectStateEntry对象的EntityState不是Unchanged的实体对象,然后,使用它的明细构建InsertUpdateInsert命令给数据库。我们从关注已经被上下文环境管理,查询出来及已经被修改开始。

5-1例子中显示了简单的情况,ObjectQuery从Contacts EntitySet中获取第一个contactcontext.Contacts的明文引用(Remember)是通过一个方法,返回Contacts的类型的ObjectQuery对象。然后,例子中,使用LINQ方法中的First仅拉出第一个实体对象。

FirstName ModifiedDate属性(Property)赋值新值,然后SaveChanges被调用。

例子5-1 查询和编辑一个Contact,然后保存到数据库

看下SQL方面的,当调用SaveChanges时,你会看到下面参数化的Update命令:

exec sp_executesql N'update [dbo].[Contact]

set [FirstName] = @0, [ModifiedDate] = @1

where ([ContactID] = @2)

',N'@0 nchar(5),@1 datetime2(7),@2 int',

@0=N'Julia',@1='2008-11-22 18:12:18.7210000',@2=1

这个命令刷新了Contact表,为ContactID为1的Contact设置了FirstName ModifiedDate的属性,这些值通过参数传递,最后的参数@2ContactID设置为1.

让我们看下当有更多实体的时候会发生什么。

例子5-2再次查询获取Robert的所有信息,返回包括有地址的列表:带有地址的Contact。然后,随意选择一个Contact,改变它的FirstNameBobby,另外一个Contact被选择,第一个Address的Street被编辑,最后,调用SaveChanges。

例子5-2 调用多个实体,调用SaveChanges

最初,12个Contact和13个Address被获取。让我们看看当SaveChanges被调用的时候,发生给数据库的命令是什么:

exec sp_executesql N'update [dbo].[Address]

set [Street1] = @0

where ([addressID] = @1)

',N'@0 nchar(15),@1 int',@0=N'One Main Street',@1=2418

 

exec sp_executesql N'update [dbo].[Contact]

set [FirstName] = @0

where ([ContactID] = @1)

',N'@0 nchar(5),@1 int',@0=N'Bobby',@1=288

 

发送给数据的第一个命令,刷新了刷新了被编辑的单个Address,仅它的Street的值和识别号AddressID被包括。下一个命令刷新Contact被发送,其它没有没有发生改变的实体,ObjectContext不会麻烦进行构建和发送。在这个方面,调用SaveChanges是非常有效的。

 

ObjectContext已知他创建命令时需要知道的一切,不但需要查看它管理的Contact和Address,而且需要查看它为12个Contact和13个Address实体所管理的ObjectStateEntry。ObjectContext首先检查EntityState看是否需要处理。因为没有涉及到的EntityState将会是Unchanged,将会忽略它。对于被修改的两个,将会比较原始值和当前值,决定什么属性要被包含到Update命令中。

当刷新完成时,两个实体将被刷新,以便EntityState设为Unchanged,原始值被当前值替换。

5.2.1 从实体框架命令到本地命令

在调用SaveChanges和数据库中执行SQL语句之间,实体框架隐藏在构建命令的后边有大量的工作在做。这个过程相似于命令和查询时如何被编译和转换到存储查询。

正如前面要注意的,这个过程的第一步是为被上下文环境所管理的实体对象的所有ObjectStateEntry的检查,EntityState为 Unchanged被忽略。前面所修改的实体,增加和删除的实体,被上下文环境处理,当命令被构建的时候,模块的元数据(概念、存储和映射层)被读取,且映射信息(表、列名)会被使用。映射也提供从模型关系到数据库外键的链接。ADO.NET提供器,比如SqlClient,做了最后构造本地命令的工作。

后面的内容,你会看到更多这方面的信息。