1)什么是DataRow's RowState and RowVersion?
DataRow's RowState是数据行的状态,RowVersion是数据行的版本。
RowState and Row Version are both enum object.
The codesnap is the following detail:
DataRowState
[Flags]
public enum DataRowState
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
Added = 4,
Deleted = 8,
Detached = 1,
Modified = 0x10,
Unchanged = 2
}
![](/Images/OutliningIndicators/None.gif)
RowVersion
public enum DataRowVersion
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
Current = 0x200,
Default = 0x600,
Original = 0x100,
Proposed = 0x400
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
2) 究竟RowState和RowVersion有什么关系呢?又个有什么用途呢?
RowState和RowVersion有一个对照关系(或许描述有点不恰当),
关系如下所示:
RowState | RowVersion |
Added | Current(Default) |
Modified | Current(Default) |
Original |
Unchanged | Current(Default) |
Original(Default) |
Detached | Proposed(Default) |
Deleted | Original (Default) |
For unchanged rowstate, default row version is also Proposed,从下面的例子中,你能看到。
从上面的表格可以看出,一个数据行有版本的控制,为什么要有这版本控制呢?
A)用于DataSet和DataTable内部实现,
B)
在用DataAdapter跟DB交互时(Call Update(DataSet)),用什么版本赋值。
当然只是在DBParameter上设置
SourceVersion
DataAdapter
public interface IDataAdapter
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
// Methods
int Fill(DataSet dataSet);
DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType);
IDataParameter[] GetFillParameters();
int Update(DataSet dataSet);
![](/Images/OutliningIndicators/InBlock.gif)
// Properties
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
MissingMappingAction MissingMappingAction
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
MissingSchemaAction MissingSchemaAction
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
ITableMappingCollection TableMappings
{ get; }
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
DBParameter
public interface IDataParameter
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
// Properties
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
DbType DbType
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
ParameterDirection Direction
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
bool IsNullable
{ get; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
string ParameterName
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
string SourceColumn
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
DataRowVersion SourceVersion
{ get; set; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
object Value
{ get; set; }
}
![](/Images/OutliningIndicators/None.gif)
3) 在DataTable.Select()和DataView.RowStateFilter区别,
public DataRow[] Select (
filterExpression,
sort,
DataViewRowState recordStates
)
Select
public Select(DataTable table, string filterExpression, string sort, DataViewRowState recordStates)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
this.table = table;
this.IndexFields = table.ParseSortString(sort);
this.indexDesc = ConvertIndexFieldtoIndexDesc(this.IndexFields);
if ((filterExpression != null) && (filterExpression.Length > 0))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.rowFilter = new DataExpression(this.table, filterExpression);
this.expression = this.rowFilter.ExpressionNode;
}
this.recordStates = recordStates;
}
![](/Images/OutliningIndicators/None.gif)
public this [
DataColumn column,
DataRowVersion version
] { get; }
public DataViewRowState RowStateFilter { get; set; }
其实在性能方面,DataView比DataTable好,DataView use index.
还是回到这个主题上吧,
DataTable的方法会返回所有的版本的数据行,而DataView仅返回相关的版本。
请看下面的例子:
Example
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
![](/Images/OutliningIndicators/None.gif)
namespace DataRowEx
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
class Program
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
static void Main(string[] args)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
TestRowStateAndRowVersion();
}
![](/Images/OutliningIndicators/InBlock.gif)
private static void TestRowStateAndRowVersion()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DataTable customerTable = new DataTable("Customers");
// Add columns
customerTable.Columns.Add("id", typeof(int));
customerTable.Columns.Add("name", typeof(string));
![](/Images/OutliningIndicators/InBlock.gif)
// Set PrimaryKey
customerTable.Columns["id"].Unique = true;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
customerTable.PrimaryKey = new DataColumn[]
{ customerTable.Columns["id"] };
![](/Images/OutliningIndicators/InBlock.gif)
// Add ten rows
for (int id = 1; id <= 3; id++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
customerTable.Rows.Add(
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
new object[]
{ customerTable.Rows.Count, string.Format("customer{0}", customerTable.Rows.Count) });
}
customerTable.AcceptChanges();
![](/Images/OutliningIndicators/InBlock.gif)
// Change one row's value:
customerTable.Rows[0].BeginEdit();
customerTable.Rows[0]["name"] = "customer Modified";
// Add one row:
DataRow dataRow = customerTable.NewRow();
dataRow["id"] = customerTable.Rows.Count;
dataRow["name"] = "customer Added";
customerTable.Rows.Add(dataRow);
![](/Images/OutliningIndicators/InBlock.gif)
// Add one row:
dataRow = customerTable.NewRow();
dataRow["id"] = customerTable.Rows.Count;
dataRow["name"] = "customer proposed";
![](/Images/OutliningIndicators/InBlock.gif)
// Delete three rows.
customerTable.Rows[1].Delete();
customerTable.Rows[2].Delete();
customerTable.Rows[3].Delete();
![](/Images/OutliningIndicators/InBlock.gif)
// Use the Select method to find all rows matching the filter.
DataRow[] foundRows =
customerTable.Select(string.Empty, string.Empty,
DataViewRowState.OriginalRows);
![](/Images/OutliningIndicators/InBlock.gif)
PrintRows(foundRows, "filtered rows by originalRows");
![](/Images/OutliningIndicators/InBlock.gif)
// Create a DataView with the table.
DataView dataView = new DataView(customerTable);
![](/Images/OutliningIndicators/InBlock.gif)
// Set the RowStateFilter to display only added and modified rows.
dataView.RowStateFilter = DataViewRowState.Added
| DataViewRowState.ModifiedCurrent;
![](/Images/OutliningIndicators/InBlock.gif)
// Print those rows. Output = "Hello" "World";
PrintView(dataView, "ModifiedCurrent and Added");
![](/Images/OutliningIndicators/InBlock.gif)
// Set filter to display on originals of modified rows.
dataView.RowStateFilter = DataViewRowState.ModifiedOriginal;
PrintView(dataView, "ModifiedOriginal");
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
// Set the RowStateFilter to display only Added and modified rows.
dataView.RowStateFilter = DataViewRowState.Deleted;
PrintView(dataView, "Deleted");
![](/Images/OutliningIndicators/InBlock.gif)
//Set filter to display only current.
dataView.RowStateFilter = DataViewRowState.CurrentRows;
PrintView(dataView, "Current");
![](/Images/OutliningIndicators/InBlock.gif)
// Set filter to display only unchanged rows.
dataView.RowStateFilter = DataViewRowState.Unchanged;
PrintView(dataView, "Unchanged");
![](/Images/OutliningIndicators/InBlock.gif)
// Set filter to display only original rows.
dataView.RowStateFilter = DataViewRowState.OriginalRows;
PrintView(dataView, "OriginalRows");
![](/Images/OutliningIndicators/InBlock.gif)
dataView.RowStateFilter = DataViewRowState.None;
PrintView(dataView, "None");
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/InBlock.gif)
private static void PrintRows(DataRow[] rows, string label)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("\n{0}", label);
if (rows.Length <= 0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("no rows found");
return;
}
![](/Images/OutliningIndicators/InBlock.gif)
foreach (DataRow row in rows)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("Row State is {0};", row.RowState);
Console.WriteLine("Current Version is {0};", row.HasVersion(DataRowVersion.Current));
Console.WriteLine("Original Version is {0};", row.HasVersion(DataRowVersion.Original));
Console.WriteLine("Proposed Version is {0};", row.HasVersion(DataRowVersion.Proposed));
![](/Images/OutliningIndicators/InBlock.gif)
if (row.RowState == DataRowState.Deleted) continue;
foreach (DataColumn column in row.Table.Columns)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.Write("({0}) ", row[column,DataRowVersion.Default]);
}
Console.WriteLine();
}
}
![](/Images/OutliningIndicators/InBlock.gif)
static private void PrintView(DataView dataView, string label)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("\n" + label);
for (int i = 0; i < dataView.Count; i++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.Write("Version is {0} -----", Enum.GetName(typeof(DataRowVersion),dataView[i].RowVersion));
Console.WriteLine(dataView[i]["name"]);
}
}
}
}
当直接访问删除的数据时,要用databview,否则会出错:
Deleted row information cannot be accessed through the row.
dataView[i].Row[1,DataRowVersion.Original]
dataView[i]["name"]
也不能用dataView[i].Row[1,DataRowVersion.Default],
对于Unchanged's RowState,如果Call BeginEdit(),没有call EndEdit(),
运行上面的例子,就知道答案了。
(4)在ADO.NET 2.0中,DatRow添加了几个新的方法:
SetAdded()and SetModified()