Entity Framework 编程
作者:Julia Lerman
译者:Abbott zhao
ObjectContext有一个方法SaveChanges,负责把对实体所造成的修改持久化到后边数据库。调用SaveChanges方法,会检查被上下文环境管理的ObjectStateEntry对象的EntityState不是Unchanged的实体对象,然后,使用它的明细构建Insert、Update和Insert命令给数据库。我们从关注已经被上下文环境管理,查询出来及已经被修改开始。
5-1例子中显示了简单的情况,ObjectQuery从Contacts EntitySet中获取第一个contact。context.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的属性,这些值通过参数传递,最后的参数@2为ContactID设置为1.
让我们看下当有更多实体的时候会发生什么。
例子5-2再次查询获取Robert的所有信息,返回包括有地址的列表:带有地址的Contact。然后,随意选择一个Contact,改变它的FirstName为Bobby,另外一个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,原始值被当前值替换。
在调用SaveChanges和数据库中执行SQL语句之间,实体框架隐藏在构建命令的后边有大量的工作在做。这个过程相似于命令和查询时如何被编译和转换到存储查询。
正如前面要注意的,这个过程的第一步是为被上下文环境所管理的实体对象的所有ObjectStateEntry的检查,EntityState为 Unchanged被忽略。前面所修改的实体,增加和删除的实体,被上下文环境处理,当命令被构建的时候,模块的元数据(概念、存储和映射层)被读取,且映射信息(表、列名)会被使用。映射也提供从模型关系到数据库外键的链接。ADO.NET提供器,比如SqlClient,做了最后构造本地命令的工作。
后面的内容,你会看到更多这方面的信息。