关于ADO.NET的其他几个方法
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
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("fname", typeof(System.String));
dt.Columns.Add("fvalue", typeof(System.Int32));
for (int i = 1; i <= 10; i++)
{
dt.Rows.Add("p" + i, i);
}
dt.AcceptChanges();
//
DataTable dtc = dt.Copy();
//
bool b = object.ReferenceEquals(dt.Rows[0], dtc.Rows[0]);//false
DataRowState s = dtc.Rows[0].RowState;//Unchanged
//Clone() and ImportRow()
DataTable dtc2 = dt.Clone();
for (int i = 0; i < 5; i++)
{
dtc2.ImportRow(dt.Rows);
}
bool b2 = object.ReferenceEquals(dt.Rows[0], dtc2.Rows[0]);//false
DataRowState s2 = dtc2.Rows[0].RowState;//Unchanged
//ItemArray
DataTable dtc3 = dt.Clone();
for (int i = 0; i < 5; i++)
{
dtc3.Rows.Add(dt.Rows.ItemArray);
//dtc3.Rows.Add(dt.Rows);//run time exception
}
bool b5 = object.ReferenceEquals(dt.Rows[0], dtc3.Rows[0]);//false
DataRowState s5 = dtc3.Rows[0].RowState;//Added
//
ArrayList al = new ArrayList();
al.Add("xy");
ArrayList alc = al.Clone() as ArrayList;
if (alc != null)
{
bool b3 = object.ReferenceEquals(al, alc);//false
bool b4 = object.ReferenceEquals(al[0], alc[0]);//true
}
}
3)Select()、Compute()
这两个方法在很多情况下都有助于你简化代码,避免每一次使用循环遍历DataTable,参见以下,
对于这两个方法中可用的表达式,参见,
http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx
Code
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("fname",typeof(System.String));
dt.Columns.Add("fvalue",typeof(System.Int32));
for (int i = 1; i <= 10; i++)
{
dt.Rows.Add("p" + i, i);
}
dt.AcceptChanges();
//
DataRow[] drs = dt.Select("fvalue>6");
PrindRows(drs);
//
drs = dt.Select("fvalue>6 and fvalue<9");//AND OR NOT
PrindRows(drs);
//
drs = dt.Select("fname like 'p1%'");
PrindRows(drs);
//
drs = dt.Select("fname in ('p1','p3')");//< > <= >= <> = IN LIKE
PrindRows(drs);
//
drs = dt.Select("fvalue=max(fvalue)");//SUM AVG MIN MAX COUNT STDEV VAR
PrindRows(drs);
//
drs = dt.Select("fvalue%2=0");//+ - * / %
PrindRows(drs);
//
drs = dt.Select("len(fname)=3");//LEN(expression) ISNULL(expression, replacementvalue) IIF(expr, truepart, falsepart) TRIM(expression) SUBSTRING(expression, start, length)
PrindRows(drs);
object o = dt.Compute("count(fname)", "fvalue>6");//4
Console.WriteLine(o.ToString());
Console.Read();
}
static void PrindRows(DataRow[] pDrs)
{
Console.WriteLine("----------------------------------");
foreach (DataRow dr in pDrs)
{
Console.WriteLine(dr["fname"].ToString().PadRight(8, ' ') + dr["fvalue"].ToString());
}
Console.WriteLine("----------------------------------");
}
}