深入NET DataTableWord文件下载.docx
- 文档编号:21712777
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:19
- 大小:22.75KB
深入NET DataTableWord文件下载.docx
《深入NET DataTableWord文件下载.docx》由会员分享,可在线阅读,更多相关《深入NET DataTableWord文件下载.docx(19页珍藏版)》请在冰豆网上搜索。
wherefname='
x'
"
;
SqlCommandcmd=newSqlCommand(sql,conn);
cmd.ExecuteNonQuery();
这是一种最直接浅显的方式,因为SQL语句就在你眼前,反过来说,这需要你对SQL命令有一定的了解。
2)使用DataAdapter.Update()
另外一种方式,是使用DataAdapter.Update()方法,这并不是说我们不需要SQL语句了,只是SQL语句拼接的工作已经交给了DataAdapter(实际上是交给了CommandBuilder)来完成(以参数的形式),例如,
stringc="
selectfname,fvaluefromtable1"
SqlCommandcmd=newSqlCommand(c,conn);
SqlDataAdapterda=newSqlDataAdapter(cmd);
SqlCommandBuilderscb=newSqlCommandBuilder(da);
//
(1)
DataTabledt=newDataTable();
da.Fill(dt);
dt.Rows[0].Delete();
//
(2)
da.Update(dt);
在这里,你看不到SQL语句,因为在你初始化SqlCommandBuilder的过程中,将自动根据表结构(基于你的Select语句)构造insert,update,delete语句。
对于上面的代码,你可以获得SQL语句内容,
DELETEFROM[table1]WHERE(([fname]=@p1)AND((@p2=1AND[fvalue]ISNULL)OR([fvalue]=@p3)))
而执行时候,会传入相应的参数值,
execsp_executesqlN'
DELETEFROM[table1]WHERE(([fname]=@p1)AND((@p2=1AND[fvalue]ISNULL)OR([fvalue]=@p3)))'
N'
@p1varchar
(1),@p2int,@p3int'
@p1='
a'
@p2=0,@p3=100
或
xecsp_executesqlN'
b'
@p2=1,@p3=NULL
由于表中只有两个列,列fname为主键列,fvalue列可空,至于为什么会出现三个参数,看看上面的SQL你就会明白了。
以下则分别是update语句、insert语句,
UPDATE[table1]SET[fname]=@p1,[fvalue]=@p2WHERE(([fname]=@p3)AND((@p4=1AND[fvalue]ISNULL)OR([fvalue]=@p5)))
INSERTINTO[table1]([fname],[fvalue])VALUES(@p1,@p2)
另外,上述C#代码中的dt.Rows[0].Delete()行写在这里只是示例作用,实际的系统中,你可能会有一个叫“Delete”的按钮,这样你可以在按钮的事件中执行Delete()操作,然后叫某个叫“Save”的按钮里写上Update(),这很常见,不多说了。
再另外,由于这些语句的构造过程中依赖于你的Select语句,所以你的Select语句中必须包含主键列,否则无法正常生成其它SQL命令。
以下我们的讨论,将主要针对第二种方式,即使用Update()进行数据更新过程中涉及的各种问题。
3、行状态
为了后续的数据操作,DataTable中引入了一个“行状态”的概念(事实上该属性属于DataRow类)。
每一个DataRow都有一个状态标志,你可以通过DataTable.Rows[i].RowState查看,对DataRow的不同操作将导致该行处于不同的状态,同时,不同的状态又导致保存数据时的不同行为。
参见下图,
1)初始状态差异
从数据库中查询并通过DataAdapter.Fill()方法填充的DataTable,其所有行的状态初始都为Unchanged(我们可以认为在Fill()方法的内部调用了AcceptChanges()方法),然而对于在程序中手工构造并添加的数据行,在未接受AcceptChanges()方法前,都为Added(行状态的不同在DataTable中是一个比较隐蔽的但又需要十分关注的问题,后续会有相应的说明),参见以下代码。
privatevoidbutton1_Click(objectsender,EventArgse)
{
try
{
dataAdapter1.Fill(dt);
DataRowStates=dt.Rows[0].RowState;
//unchanged
}
catch
}
privatevoidbutton2_Click(objectsender,EventArgse)
DataTabledt=newDataTable();
dt.Columns.Add("
fname"
);
fvalue"
dt.Rows.Add("
zhang"
100);
//added
2)理解Delete()
此方法并未真正移除DataRow(除非此行原状态为Added),而只是将RowState状态变成了Deleted(当然这会导致你无法使用正常的索引方式访问此行的数据)。
对于Added状态的行执行Delete()操作,将导致DataTable行数减少,这点需要注意,因为它可能导致你在使用for循环遍历时出现索引越界异常。
privatevoidbutton7_Click(objectsender,EventArgse)
//
dt.Rows[0].Delete();
intc=dt.Rows.Count;
//0
privatevoidbutton8_Click(objectsender,EventArgse)
dt.AcceptChanges();
//1
3)Exception:
Deletedrowinformationcannotbeaccessedthroughtherow.
DataRowdr=dt.Rows[0];
//Noerror
objecto=dt.Rows[0]["
];
//Exception,rowcanbeaccessed,butrowdatacannot
4)理解AcceptChanges()
此方法容易给人误解,以为在调用它之后对DataTable所做的所有更改将会被提交到Database。
事实上,此方法跟Database没有直接的关系(注意),它只直接影响各DataRow的RowState(具体地说来是将所有状态为Deleted的行真正移除,所有状态为Added或Modified的行都变成Unchanged)。
与Database有直接相关的是DataAdapter.Update()方法,它是真正负责执行相关SQL命令的地方。
但是,从另一方面来说,没有直接的影响,言外之意就是有间接的影响,由于它影响了所有DataRow的RowState,而DataAdapter.Update()方法在执行SQL命令时必须依据RowState以确定使用insert、update、或delete命令。
举个例子,如果你在DataAdapter.Update()调用之前执行AcceptChanges()方法,这将阻止所有对Database的更改,因此对这两个方法调用的顺序应有充分的考虑。
另外,DataSet、DataTable、DataRow都有AcceptChanges()方法,这些方法除了影响的范围大小不同之外,没有本质的区别。
5)DataRowState与Update()
不同的数据行状态,将导致最终DataAdapter.Update()出现不同的行为,例如对于Added状态的行,将导致insert操作、Modified状态将导致update操作、Deleted状态将导致delete操作。
6)使用DataRowState
除了Update()方法内部使用DataRowState外,在我们自己写的代码中,也可以将它与GetChanges()方法配合使用,以获取DataTable的当前变化,参见以下代码,在你获得所有发生更新的行后,实际上你可以自己构造UpdateSQL命令,而不使用CommandBuilder,当然这需要用到稍后会提到的DataRowVersion。
privatevoidbutton4_Click(objectsender,EventArgse)
dt.Rows[0]["
]=101
//getallModifiedrows,thenyoucanuseUPDATESQLtosavedata.
DataTabledt1=dt.GetChanges(DataRowState.Modified);
7)状态Detached
除了上图中给出的几种行状态外,还有一种特殊的状态Detached,这种状态表示已初始化但未添加到DataTable中的数据行,此状态我们不必太关心。
参见,
privatevoidbutton3_Click(objectsender,EventArgse)
DataRowdr=dt.NewRow();
DataRowStates=dr.RowState;
//detached
4、行状态、行版本、行数据版本
行版本(DataRowVersion)描述数据行的版本;
行数据版本(DataViewRowState)描述数据行中数据的版本。
这两个概念令人困惑,我认为可以仅仅从用法上对它们进行了解,毕竟我们使用它们的机会并非很大。
1)使用DataRowVersion
关于DataRowVersion,以状态为Modified的行为例,它包含两个DataRowVersion(即存储了两行数据):
Current,Original,分别存储该行修改后与修改前的数据,也就是说,行版本实际可以帮助RejectChanges()等方法实现一个类似于“回滚”的功能。
]=101;
inti=Convert.ToInt32(dt.Rows[0]["
DataRowVersion.Original]);
//100
inti2=Convert.ToInt32(dt.Rows[0]["
DataRowVersion.Current]);
//101
同理你可以借助DataRowVersion来访问Deleted的数据,前面我们提到了对于Deleted的数据,使用dt.Rows[0]["
]访问将引发异常,可以使用
dt.Rows[0]["
DataRowVersion.Original]。
2)DataRowVersion与Update()
现在我们回想一下,当我们使用CommandBuilder构造完Update,Insert,Delete命令之后,那些SQL命令中的参数怎么办?
我们知道在SQL命令执行之前,我们必须为所有输入参数指定参数值,那么Update()方法内部是如何工作的?
这就有赖于DataRowVersion了。
我们可以简单看一下Update()方法使用过程中涉及的相关.NET源码,
System.Data.Common.DbDataAdapter
protectedvirtualintUpdate(DataRow[]dataRows,DataTableMappingtableMapping);
在Update()方法中,调用了ParameterInput(),下面是该方法的摘要,
privatevoidParameterInput(IDataParameterCollectionparameters,StatementTypetypeIndex,DataRowrow,DataTableMappingmappings)
foreach(IDataParameterparameterinparameters)
if(column!
=null)
DataRowVersionparameterSourceVersion=GetParameterSourceVersion(typeIndex,parameter);
parameter.Value=row[column,parameterSourceVersion];
在ParameterInput()方法中,调用了GetParameterSourceVersion()方法,
privatestaticDataRowVersionGetParameterSourceVersion(StatementTypestatementType,IDataParameterparameter)
switch(statementType)
caseStatementType.Select:
caseStatementType.Batch:
throwADP.UnwantedStatementType(statementType);
caseStatementType.Insert:
returnDataRowVersion.Current;
caseStatementType.Update:
returnparameter.SourceVersion;
caseStatementType.Delete:
returnDataRowVersion.Original;
throwADP.InvalidStatementType(statementType);
以行被更新的情况为例,在为参数的赋值的过程中,系统会将相应要更新的DataRow一并传入,同时对于Update语句,
我们要了解的一点是,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()
privatevoidbutton9_Click(objectsender,EventArgse)
zhao"
qian"
sun"
dt.Rows[1]["
dt.Rows[2].Delete();
li"
//objecto=dt.Rows[2]["
DataRowVersion.Original];
StringBuildersb=newStringBuilder();
DataRow[]drs=dt.Select(null,null,DataViewRowState.Added);
sb.AppendLine("
-----------------------------------------------"
Added:
for(inti=0;
i<
drs.Length;
i++)
sb.AppendLine(drs[i]["
].ToString()+"
:
"
+drs[i]["
].ToString());
drs=dt.Select(null,null,DataViewRowState.CurrentRows);
CurrentRows:
].ToString()+"
+drs[i]["
drs=dt.Select(null,null,DataViewRowState.Deleted);
Deleted:
DataRowVersion.Original].ToString()+"
fvalue
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 深入NET DataTable 深入 NET