深入.NET DataTable2

本文深入探讨了数据行的状态和版本概念,包括行版本(DataRowVersion)与行数据版本(DataViewRowState),解释了如何利用这些概念进行数据管理和查询优化。通过具体的.NET代码示例,展示了如何在实际开发中运用这些特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4、行状态、行版本、行数据版本
行版本(DataRowVersion)描述数据行的版本;
行数据版本(DataViewRowState)描述数据行中数据的版本。
这两个概念令人困惑,我认为可以仅仅从用法上对它们进行了解,毕竟我们使用它们的机会并非很大。  

1)
使用DataRowVersion
关于DataRowVersion,以状态为Modified的行为例,它包含两个DataRowVersion(即存储了两行数据):Current,Original,分别存储该行修改后与修改前的数据,也就是说,行版本实际可以帮助RejectChanges()等方法实现一个类似于“回滚”的功能。 

Code
同理你可以借助 DataRowVersion 来访问 Deleted 的数据,前面我们提到了对于 Deleted 的数据, 使用 dt.Rows[0]["fvalue"] 访问 将引发异常,可以使用
dt.Rows[0]["fvalue", DataRowVersion.Original]

2) DataRowVersion
Update()
现在我们回想一下,当我们使用 CommandBuilder 构造完 Update,Insert,Delete 命令之后,那些 SQL 命令中的参数怎么办?我们知道在 SQL 命令执行之前,我们必须为所有输入参数指定参数值,那么 Update() 方法内部是如何工作的?这就有赖于 DataRowVersion 了。
 
我们可以简单看一下 Update() 方法使用过程中涉及的相关 .NET 源码,
System.Data.Common.DbDataAdapter
protected virtual int Update(DataRow[] dataRows, DataTableMapping tableMapping);
Update() 方法中,调用了 ParameterInput() ,下面是该方法的摘要  
Code
ParameterInput() 方法中,调用了 GetParameterSourceVersion() 方法  
Code
以行被更新的情况为例,在为参数的赋值的过程中,系统会将相应要更新的 DataRow 一并传入,同时对于 Update 语句,
UPDATE [table1] SET [fname] = @p1, [fvalue] = @p2 WHERE (([fname] = @p3) AND ((@p4 = 1 AND [fvalue] IS NULL) OR ([fvalue] = @p5)))
我们要了解的一点是, 5 个参数中 @p1,@p2 是一类, @p3, @p5 是一类,它们的区别在于,前一类的 SourceVersion Current ,而后一类的 SourceVersion Original ,这在上述的 GetParameterSourceVersion() 方法中被用到,所以!!,针对传入的需要更新的 DataRow Update() 方法内部将使用当前值(即修改后的值)填充 @p1,@p2 ,而使用原始值(即修改前的值)填充 @p3, @p5 Insert,delete 同理。

3)理解DataRowVersion.Default
对于 Added Modified Deleted 状态的行,其 Default 版本实际是 Current 版本,对于 Unchanged 则无甚区别。
 
4) 使用 DataViewRowState
(1) 配合 DataTable.Select()  
Code
 

结果输出:
-----------------------------------------------
Added:
li: 100
-----------------------------------------------
CurrentRows:
zhao: 100
qian: 101
li: 100
-----------------------------------------------
Deleted:
sun: 100
-----------------------------------------------
ModifiedCurrent:
qian: 101
-----------------------------------------------
ModifiedOriginal:
qian: 101
-----------------------------------------------
OriginalRows:
zhao: 100
qian: 101
sun: 100
-----------------------------------------------
Unchanged:
zhao: 100
 
(2) 配合 DataView.RowFilter   
Code
//
-----------------------------------------------  
Added & ModifiedCurrent:
qian: 101
li: 100
-----------------------------------------------
 
5)DataViewRowState 中的“复合版本”
DataViewRowState 包含多个枚举成员,我可以给出每个枚举成员对应的 int 值,
Added                     4
CurrentRow              22
Deleted                   8
ModifiedCurrent        16
ModifiedOriginal        32
None                       0
OriginalRow              42
Unchanged              2
你可以发现,其中的两个状态 CurrentRow OriginalRow 实际是经由其它几种状态二进制或运算的结果,
CurrentRow=Added|ModifiedCurrent|Unchanged
OriginalRow=Deleted|ModifiedOriginal|Unchanged
 
5、了解其它几个方法
1)Delete() Remove() Clear()
DataRow.Delete()
DataRowCollection.Remove()
DataTable.Clear() DataSet.Clear()
正如前面所述,对于 DataRow Delete() 方法,其内部的处理并未真正删除此行,而只是将行标识为 Deleted ,并“移除”了它的 Current 版本。这样,当使用 DataAdapter Update() 进行更新时,其内部机制可以根据仍然存在的 Original 版本数据,为 DeleteCommand 填充参数,完成更新数据库的操作。
Clear() 方法则完全删除了堆上的数据行对象,并且将对数据引用置空(这点可以参见 Clear() 方法的反编译代码),这种情况下无法生成可执行的 DeleteCommand ,这就是说,当你用 Clear() 方法“清空” DataTable 后,使用 Update() 方法并不能像你预想的一样将对应的数据库表数据删除。
另外,需要注意一点是 Delete() 并不导致数据行减少(除非原行是 Added 状态),当然,如果是对 Added 状态的行执行 Delete() ,则导致行数减少。当你使用 for 循环时,这可能会造成问题。
另外,我们还有一个方法: DataRowCollection.Remove() ,其作用类似于 Clear() ,是彻底地移除行,假设你是使用 DataAdapter.Update() 方法更新 Database ,那么你将没有机会将你的删除操作同步到 Database 中。

2)Copy() Clone()
.NET 中有两类拷贝,浅拷贝 (Shadow copy) 、深拷贝 (Deep copy) ,对于大多数我们所见的类(比如常见的集合类等等),没有深拷贝方法,大多数会有一个浅拷贝方法 Clone() 我唯一所见的一个深拷贝方法是 DataTable.Copy() ,同时, DataTable.Clone() 方法也比较特殊,因为它并非是浅拷贝方法,而是拷贝 DataTable 的结构(不包含数据)。
顺便提一下深、浅拷贝的区别,浅拷贝创建原对象类型的一个新实例,复制原对象的所有值类型成员,对于引用类型成员,则只复制该值的指针。深拷贝则复制原对象的所有成员,对于引用类型成员,亦复制其所指的堆上的对象。   

Code

 
3)Select()Compute()
这两个方法在很多情况下都有助于你简化代码,避免每一次使用循环遍历DataTable,参见以下,
对于这两个方法中可用的表达式,参见,
http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx 

Code


----------------------------------
p7      7
p8      8
p9      9
p10     10
----------------------------------
 
----------------------------------
p7      7
p8      8
----------------------------------
 
----------------------------------
p1      1
p10     10
----------------------------------
 
----------------------------------
p1      1
p3      3
----------------------------------
 
----------------------------------
p10     10
----------------------------------
 
----------------------------------
p2      2
p4      4
p6      6
p8      8
p10     10
----------------------------------
 
----------------------------------
p10     10
----------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值