首页 > 编程 > .NET > 正文

ADO.NET中的多数据表操作浅析—修改

2024-07-10 13:05:23
字体:
来源:转载
供稿:网友
ado.net中的多数据表操作浅析—修改

作者:郑佐??????? 2004-8-5


三、更新数据集

首先需要说明的是我这里去掉了order details表,对两个表的操作只是其中的几个字段。下面是窗体界面:



图3-1

单选框用来选择不同的更新方法。

在dataaccess类中增加两个类成员变量:

???? private sqldataadapter _customerdataadapter; //客户数据适配器

???? private sqldataadapter _orderdataadapter; //订单数据适配器

?

customerdataadapter在构造函数中的初始化为

//实例化_customerdataadapter

sqlcommand selectcustomercomm = new sqlcommand("getcustomer",_conn);

selectcustomercomm.commandtype = commandtype.storedprocedure;

selectcustomercomm.parameters.add("@customerid",sqldbtype.nchar,5,"customerid");

????????

sqlcommand insertcustomercomm = new sqlcommand("addcustomer",_conn);

insertcustomercomm.commandtype = commandtype.storedprocedure;

insertcustomercomm.parameters.add("@customerid",sqldbtype.nchar,5,"customerid");

insertcustomercomm.parameters.add("@companyname",sqldbtype.nvarchar,40,"companyname");

insertcustomercomm.parameters.add("@contactname",sqldbtype.nvarchar,30,"contactname");

?

sqlcommand updatecustomercomm = new sqlcommand("updatecustomer",_conn);

updatecustomercomm.commandtype = commandtype.storedprocedure;

updatecustomercomm.parameters.add("@customerid",sqldbtype.nchar,5,"customerid");

updatecustomercomm.parameters.add("@companyname",sqldbtype.nvarchar,40,"companyname");

updatecustomercomm.parameters.add("@contactname",sqldbtype.nvarchar,30,"contactname");

?????????????

sqlcommand deletecustomercomm = new sqlcommand("deletecustomer",_conn);

deletecustomercomm.commandtype = commandtype.storedprocedure;

deletecustomercomm.parameters.add("@customerid",sqldbtype.nchar,5,"customerid");

?

_customerdataadapter = new sqldataadapter(selectcustomercomm);

_customerdataadapter.insertcommand = insertcustomercomm;

_customerdataadapter.updatecommand = updatecustomercomm;

_customerdataadapter.deletecommand = deletecustomercomm;

?

上面的代码完全可以用设计器生成,觉得有些东西自己写感觉更好,不过代码还是很多。

对于_orderdataadapter的初始化同上面的差不多,这里我们只看订单增加的处理,下面是存储过程:

create procedure? addorder

(

???? @orderid int out,

???? @customerid nchar(5),

???? @orderdate datetime

)

as

insert into orders

(

???? customerid ,

???? orderdate

)

values

(

???? @customerid ,

???? @orderdate

)

--select @orderid = @@identity

set @orderid = scope_identity()

go

?

orderid自动增长值的获取通过输出参数来完成,这个相当不错,如果使用sqldataadapter.rowupdated事件来处理那效率会很低。

对insertordercomm对象的定义为:

sqlcommand insertordercomm = new sqlcommand("addorder",_conn);

insertordercomm.commandtype = commandtype.storedprocedure;

insertordercomm.parameters.add("@orderid",sqldbtype.int,4,"orderid");

insertordercomm.parameters["@orderid"].direction = parameterdirection.output;

insertordercomm.parameters.add("@orderdate",sqldbtype.datetime,8,"orderdate");

insertordercomm.parameters.add("@customerid",sqldbtype.nchar,5,"customerid");

?

在实现数据的更新方法之前我们先来明确一些更新逻辑:

对于标记为删除的行,先删除订单表的数据,再删除客户表的数据;

对于标记为添加的行,先添加客户表的数据,再添加订单表的数据。

?

(1)实现用获取修改过的dataset的副本子集来更新数据的方法。

这也是调用xml web service更新数据的常用方法,先来看第一个版本,子集的获取通过dataset.getchangs方法来完成。

//使用数据集子集更新数据

public void updatecustomerorders(datasetorders ds)

{????????????

???? dataset dsmodified = ds.getchanges(datarowstate.modified);//获取修改过的行

???? dataset dsdeleted = ds.getchanges(datarowstate.deleted);//获取标记为删除的行

???? dataset dsadded = ds.getchanges(datarowstate.added);//获取增加的行

???? try

???? {???

???????? _conn.open();//先添加客户表数据,再添加订单表数据

???????? if(dsadded != null)

???????? {

????????????? _customerdataadapter.update(dsadded,"customers");

????????????? _orderdataadapter.update(dsadded,"orders");

????????????? ds.merge(dsadded);

???????? }

???????? if(dsmodified != null)//更新数据表

???????? {

???????? ???? _customerdataadapter.update(dsmodified,"customers");

????????????? _orderdataadapter.update(dsmodified,"orders");

????????????? ds.merge(dsmodified);

???????? }

???????? if(dsdeleted != null)//先删除订单表数据,再删除客户表数据

???????? {

????????????? _orderdataadapter.update(dsdeleted,"orders");

????????????? _customerdataadapter.update(dsdeleted,"customers");

????????????? ds.merge(dsdeleted);

???????? }?????????????????

???? }

???? catch(exception ex)

???? {

???????? throw new exception("更新数据出错",ex);

???? }

???? finally

???? {

???????? if(_conn.state != connectionstate.closed)

????????????? _conn.close();

???? }

}

上面的方法看上去比较清晰,不过效率不会很高,至少中间创建了三个dataset,然后又进行了多次合并。

(2)另一方法就是引用更新,不创建副本。

相对来说性能会高许多,但是如果用在web服务上传输的数据量会更大(可以结合两个方法进行改进)。具体的实现就是通过datatable.select方法选择行状态来实现。

//引用方式更新数据

public void updatecustomerorders(dataset ds)

{

???? try

???? {???

???????? _conn.open();

???????? //先添加客户表数据,再添加订单表数据 ???? _customerdataadapter.update(ds.tables["customers"].select("","",dataviewrowstate.added));

???? _orderdataadapter.update(ds.tables["orders"].select("","",dataviewrowstate.added));

???? //更新数据表

???? _customerdataadapter.update(ds.tables["customers"].select("","",dataviewrowstate.modifiedcurrent));

???? _orderdataadapter.update(ds.tables["orders"].select("","",dataviewrowstate.modifiedcurrent));

//先删除订单表数据,再删除客户表数据

???? _orderdataadapter.update(ds.tables["orders"].select("","",dataviewrowstate.deleted));

???? _customerdataadapter.update(ds.tables["customers"].select("","",dataviewrowstate.deleted));???????????

???? }

???? catch(exception ex)

???? {

???????? throw new exception("更新数据出错",ex);

???? }

???? finally

???? {

???????? if(_conn.state != connectionstate.closed)

????????????? _conn.close();

???? }

}

结合上面的两个方法我们可想到调用web service有更合理的方法来完成。

(3)使用事务

public void updatecustomerorderswithtransaction(dataset ds)

{

???? sqltransaction trans = null;

???? try

???? {???

???????? _conn.open();

???????? trans = _conn.begintransaction();

???????? _customerdataadapter.deletecommand.transaction = trans;

???????? _customerdataadapter.insertcommand.transaction = trans;

???????? _customerdataadapter.updatecommand.transaction = trans;

???????? _orderdataadapter.deletecommand.transaction = trans;

???????? _orderdataadapter.insertcommand.transaction = trans;

???????? _orderdataadapter.updatecommand.transaction = trans;

???? _customerdataadapter.update(ds.tables["customers"].select("","",dataviewrowstate.added));

?????????????????? _orderdataadapter.update(ds.tables["orders"].select("","",dataviewrowstate.added));

???? _customerdataadapter.update(ds.tables["customers"].select("","",dataviewrowstate.modifiedcurrent));

???? _orderdataadapter.update(ds.tables["orders"].select("","",dataviewrowstate.modifiedcurrent));

???? _orderdataadapter.update(ds.tables["orders"].select("","",dataviewrowstate.deleted));

???? _customerdataadapter.update(ds.tables["customers"].select("","",dataviewrowstate.deleted));?

???? ???? trans.commit();

???? }

???? catch(exception ex)

???? {

???????? trans.rollback();

???????? throw new exception("更新数据出错",ex);

???? }

???? finally

???? {

???????? if(_conn.state != connectionstate.closed)

????????????? _conn.close();

???? }

}

最后让我们来看看窗体的按钮更新事件的代码:

private void buttonupdate_click(object sender, system.eventargs e)

{

????????????? //提交编辑数据

???? this.bindingcontext[this._ds].endcurrentedit();

????

???? if(radiobuttonref.checked == true)//引用方式更新

???????? _dataaccess.updatecustomerorders((dataset)_ds);

???? else if(radiobuttontrans.checked == true)//启用事务更新数据表

???????? _dataaccess.updatecustomerorderswithtransaction((dataset)_ds);

???? else

???? {

???????? datasetorders changeddata =? (datasetorders)_ds.getchanges();

???????? if(radiobuttonweb.checked == true)//web服务的更正更新

???????? {?????????????????????

????????????? _dataaccess.updatecustomerorders((dataset)changeddata);

???????? }

???????? else//创建副本合并方式更新

???????? {?????????????????

????????????? _dataaccess.updatecustomerorders(changeddata);

???????? }

???????? //去除订单表中添加的虚拟行

???????? foreach(datarow row in _ds.orders.select("","",dataviewrowstate.added))

????????????? _ds.orders.removeordersrow((datasetorders.ordersrow)row);

???????? //去除客户表中添加的虚拟行

???????? foreach(datarow row in _ds.customers.select("","",dataviewrowstate.added))

????????????? _ds.customers.removecustomersrow((datasetorders.customersrow)row);

???????? _ds.merge(changeddata);

???? }

???? //提交数据集状态

???? _ds.acceptchanges();

}

?

本文参考:《ado.net core reference》

欢迎交流:(秋枫的blog)http://blog.csdn.net/zhzuo

?

?

?


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表