大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> NET专区 -> .NET 数据访问架构指南(二)

.NET 数据访问架构指南(二)

时间: 2021-07-31 作者:daque

运用机动化工作 机动化工作简化了编制程序模子,由于它们不须要精确地发端新工作处置进程,或精确实行或废除工作。但是,机动化工作的最大便宜是它们能与dtc贯串起来,这就使单个工作不妨扩充到多个散布式数据源中。在巨型散布式运用步调中,这个便宜是很要害的。纵然经过细工对dtc径直编制程序来遏制散布式工作是大概的,但机动化工作处置极大的简化了处事量,而且它是为鉴于组件的体例而安排的。比方,不妨简单地以证明办法摆设多个组件以实行包括了单个工作处置的工作。 机动化工作依附于com+供给的散布式工作处置扶助个性。截止,惟有效劳组件(即从servicedcomponent类中派生的组件)不妨运用机动化工作。 要为机动化工作处置摆设类,操纵如次: 从坐落enterpriseservices称呼空间的servicedcomponent类中派生新类。 经过transaction属性设置类的工作处置需要。来自transactionoption的列举值确定了怎样在com+类中摆设类。可与此属性一齐树立的其它属性囊括工作处置辨别等第和超时下限。 为了制止必需精确选定工作处置截止,不妨用autocomplete属性对本领举行解释。即使那些本领开释特殊,工作将机动废除。提防,即使须要,仍不妨径直抉择工作处置截止。更多确定,见正文稍后决定工作处置截止的节。 更多消息 对于com+机动化工作的更多消息,可在平台sdk文书档案中探求“经过com+的机动化工作”获得。 对于.ne t工作处置类的示例,见附录中的怎样源代码.net工作处置。 摆设工作处置辨别级别 用来com+1.0版--即运转在windows 2000中的com+--的工作处置辨别级别被序列化了。如许做供给了最高的辨别等第,却是以本能为价格的。体例的完全含糊量被贬低了。由于所波及到的资源处置器(典范地是数据库)在工作处置功夫必需维持读和写锁。在此功夫,其它一切工作处置都被阻断了,这种情景将对运用步调的扩充本领爆发极大报复。 随微软windows .net刊行的com+ 1.5版承诺有com+目次中按组件摆设工作处置辨别等第。与工作中根组件关系的树立确定了工作处置的辨别等第。其余,同一工作流中的里面子组件具有的工作处置等第必需不许高于要组件所设置的等第。即使不是如许,当子组件范例化时,将引导缺点。 对.net处置类,transaction属性扶助一切的国有isolation属性。你不妨用此属性报告式地指定一特出辨别等第,如底下的代码所示: [transaction(transactionoption.supported, isolation=transactionisolationlevel.readcommitted)]public class account : servicedcomponent{ . . .}更多消息 对于摆设工作处置辨别等第及其它windows .net com+巩固个性的更多消息,见msdn期刊2001年8月期的“windows xp:运用com+ 1.5的巩固个性使你的组件更健康”一文。 决定工作处置截止 在单个工作流的一切工作处置组件左右文中,机动化工作处置截止由工作废除标记和普遍性标记的状况确定。当工作流中的根组件变成非震动状况(而且遏制权归来挪用者)时,决定工作处置截止。这种情景在图第5中学获得了演练,此图表露的是一个典范的钱庄基金传递工作。 图5 工作流左右文 当根东西(在本例中是东西)变为非震动状况,而且存户的本领挪用归来时,决定工作处置截止。在任何左右文中的任何普遍性标记被设为假,或即使工作处置废除标记设为真,那么底层的物理dtc工作将被废除。 不妨以底下两种办法之一从.net东西中遏制工作处置截止: 不妨用autocomplete属性对本领举行解释,并让.net机动寄存将确定工作处置截止开票。即使本领开释特殊,运用此属性,普遍性标记机动地被设为假(此值最后使工作废除)。即使本领归来而没有开释特殊,那么普遍性标记将设为真,此值指出组件乐于实行工作。这并没有获得保护,由于它依附于同一工作流中其它东西的开票。 不妨挪用contextutil类的静态本领setcomplete或 setabort,那些本领辨别将普遍性标记设为真或假。 重要性大于10的sql server缺点将引导处置数据供给器开释sqlexception典型的特殊。即使本领缓存并处置特殊,就要保证大概经过细工废除了工作,大概本领被标志了[autocomplete],以保护特殊能传播回挪用者。 autocomplete本领 对于标志了属性的本领,实行底下操纵: 将sqlexception传播加挪用仓库。 将sqlexception封装在外部不同中,并传播回挪用者。也不妨将特殊封装在对挪用者更有意旨的特殊典型中。 特殊即使不许传播,将引导东西不会提出废除工作,进而忽略数据库缺点。这表示着共享同一工作流的其它东西的胜利操纵将被提交。 底下的代码缓存了sqlexception,而后将它径直传播回挪用者。工作处置最后将被废除,由于东西的普遍性标记在东西变为非震动状况时机动被设为假。 [autocomplete]void somemethod(){ try { // open the connection, and perform database operation . . . } catch (sqlexception sqlex ) { logexception( sqlex ); // log the exception details throw; // rethrow the exception, causing the consistent // flag to be set to false. } finally { // close the database connection . . . }}non-autocomlete本领 对于没有autocomplete的属性的本领,必需: 在catch块内挪用contextutil.setabort以中断工作处置。这就将相容标记树立为假。 即使没有爆发特殊事变,挪用contextutil.setcomplete,以提交工作,这就将相容标记树立为真(缺省状况)。 代码说领会这种本领。 void someothermethod(){ try { // open the connection, and perform database operation . . . contextutil.setcomplete(); // manually vote to commit the transaction } catch (sqlexception sqlex) { logexception( sqlex ); // log the exception details contextutil.setabort(); // manually vote to abort the transaction // exception is handled at this point and is not propagated to the caller } finally { // close the database connection . . . }}提防 即使有多个catch块,在本领发端的功夫挪用contextvtil.setabort,以及在try块的结束挪用contextutil.setcomplete城市变得简单。用这种本领,就不须要在每个catch块中反复挪用contextutil.setabort。经过这种本领决定的相容标记的树立只在本领归来时灵验。 对于特殊事变(或轮回特殊),必需把它传播到挪用仓库中,由于这使得挪用代码觉得工作处置波折。它承诺挪用代码做出优化采用。比方,在钱庄资本转账中,即使债务操纵波折,则转帐分支不妨确定不实行债务操纵。 即使把相容标记树立为假而且在归来时没有展示特殊事变,则挪用代码就没有方法领会工作处置能否确定波折。固然不妨归来boolean值或树立boolean输入参数,但仍旧该当前后普遍,经过表露特殊事变以表白有缺点爆发。如许代码就有一种规范的缺点处置本领,所以更简略、更具备相容性。 数据分页 在散布式运用步调中运用数据举行分页是一项一致的诉求。比方,用户大概获得书的列表而该列表又不不妨一次实足表露,用户就须要在数据上实行少许熟习的操纵,比方欣赏下一页或上一页的数据,大概跳到列表的第一页或结果一页。 这局部实质将计划实行这种功效的选项,以及每种选项在本能和缩放性上的功效。 选项比拟 数据分页的选项有: 运用sqldataadapter的fill本领,未来自查问处的截止弥补到dataset中。 经过com的可彼此操纵性运用ado,并运用效劳器光标。 运用保存的进程细工实行数据分页。 对数据举行分页的最预选项依附于下列成分: 扩充性诉求 本能诉求 搜集带宽 数据库效劳器的保存器和功率 中级效劳器的保存器和功率 由分页查问所归来的行数 数据总页数的巨细 本能尝试表白运用保存进程的细工本领在很大的应力程度范畴上都供给了最好本能。但是,因为细工本领在效劳器上实行处事,即使大局部站点功效都依附数据分页功效,那么效劳器本能就会成一个要害因素。为保证这种本领能符合特出情况,该当尝试百般特出诉求的选项。 底下将计划百般各别的选项。 运用sqldataadapter 如前方所计划的,sqldataadapter是用来把来自数据库的数据弥补到dataset中,过载的fill本领中的任一个都须要两个平头索引值(如次列代码所示): public int fill( dataset dataset, int startrecord, int maxrecords, string srctable);startrecord值标示从零发端的记载开始索引值。maxrecord值表白从startrecord发端的记载数,并将正片到新的dataset中。 sqldataadapter在里面运用sqldatareader实行查问并归来截止。sqldataadapter读取截止并创造鉴于来自saldatareader的数据的dataset。sqldataadapter经过startrecord和maxrecords把一切截止都正片到新天生的dataset中,并抛弃不须要的数据。这表示着很多不需要的数据将潜伏的经过搜集加入数据考察存户--这是这种本领的重要缺点。 比方,即使有1000个记载,而须要的是第900到950个记载,那么前方的899个记载将仍旧穿梭搜集而后被抛弃。对于小数目的记载,这种开支大概是比拟小的,但即使对准洪量数据的分页,则这种开支就会特殊宏大。 运用ado 实行分页的另一个选项是运用鉴于com的ado举行分页。这种本领的目的是赢得考察效劳器光标。效劳器光标经过ado recordset东西表露。不妨把recordset光目标场所树立到aduseserver中。即使你的ole db供给器扶助这种树立(如sqloledb那么),就不妨运用效劳器光标。如许就不妨运用光标径直导航到开始记载,而不须要将一切数据传过搜集加入考察数据的用户代码中。 这种本领有底下两个缺陷: 在大普遍情景下,大概须要将归来到recordset东西中的记载翻译成dataset中的实质,再不在存户处置的代码中运用。固然oledbdataadapter真实在获得ado recordset东西并把它翻译成dataset时过载了fill本领,然而并没有运用特出记载举行发端与中断操纵的功效。独一实际的选项是把发端记载挪动到recordset东西中,轮回每个记载,而后细工正片数据得手工天生的新dataset中。这种操纵,更加是运用com interop挪用,其便宜大概不只仅是不须要在搜集上传输过剩的数据,更加对于小的dataset更鲜明。 从效劳器输入所需数据时,将维持贯穿和效劳器光标盛开。在数据库效劳器上,光目标盛开与保护须要高贵的资源。固然该选项普及了本能,然而因为为延迟的功夫两耗费效劳器资源,进而也有大概贬低可扩充性。 供给细工实行 在本局部中计划的数据分页的结果一个选项是运用保存进程细工实行运用步调的分页功效。对于包括独一要害字的表格,实行保存进程对立简单少许。而对于没有独一要害字的表格(也不该当有很多要害字),该进程会对立搀杂少许。 带有独一要害字的表格的分页 即使表格包括一个独一要害字,就不妨运用where条件中的要害字创造从某个特出行开始的截止树立。这种本领,与用来控制截止树立巨细的set rowcount状况是相配合的,供给了一种灵验的分页道理。这一本领将在底下保存的代码中证明: create procedure getproductspaged@lastproductid int,@pagesize intasset rowcount @pagesizeselect *from productswhere [standard search criteria]and productid > @lastproductidorder by [criteria that leaves productid monotonically increasing]go这个保存进程的挪用步调只是保护lastproductid的值,并经过所选的贯串挪用之间的页的巨细减少或减小该值。 不带有独一要害字的表格的分页 即使须要分页的表格没有独一要害字,不妨商量增添一个--比方运用标识栏。如许就不妨实行上头计划的分页计划了。 只有不妨经过贯串截止记载中的两个或更多地区来爆发独一性,就仍旧有大概实行无独一要害字表格的灵验分页计划。 比方,参观下列表格: col1 col2 col3 other columns… a 1 w … a 1 x . a 1 y . a 1 z . a 2 w . a 2 x . b 1 w … b 1 x . 对于该表,贯串col 、col2 和col3就大概爆发一种独一性。如许,就不妨运用底下保存进程中的本领实行散布道理: create procedure retrievedatapaged@lastkey char(40),@pagesize intasset rowcount @pagesizeselectcol1, col2, col3, col4, col1+col2+col3 as keyfieldfrom sampletablewhere [standard search criteria]and col1+col2+col3 > @lastkeyorder by col1 asc, col2 asc, col3 ascgo存户维持保存进程归来的keyfield栏的结果值,而后又插入回到保存进程中以遏制表的分页。 固然细工实行减少了数据库效劳器上的应急,但它制止了在搜集上传输不需要的数据。本能尝试表白在所有应急程度中这种本领都处事杰出。但是,按照站点处事所波及的数据分页功效的几何,在效劳器长进行细工分页大概影相应用步调的可扩充性。该当在地方情况中运转本能尝试,为运用步调找到最符合的本领。 附录 怎样为一个.net类起用东西构造 要运用enterprise (com+)services为东西构造起用.net处置的类,须要实行下列办法: 从坐落system. enterprise services名字空间中的serviced component中程导弹出所需类。 using system.enterpriseservices;public class dataaccesscomponent : servicedcomponent为该类增添construction enabled属性,并有理地指定缺省构造字符串,该缺省值生存在com+目次中,处置员不妨运用组件效劳微软处置遏制台(mnc)的snap-in来保护该缺省值。 [constructionenabled(default="default dsn")]public class dataaccesscomponent : servicedcomponent供给假造construct本领的替代实行计划。该本领在东西谈话结构步调之后挪用。在com目次中生存的构造字符串是该本领的独一字符串。 public override void construct( string constructstring ){ // construct method is called next after constructor. // the configured dsn is supplied as the single argument}经过assembly key文献或assembly key name属性为该汇编供给一个强名字。任何用com+效劳备案的汇编必需有一个强名字。对于带有强名字汇编的更多消息,参考:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconworkingwithstrongly- namedassemblies.asp。 [assembly: assemblykeyfile("dataservices.snk")]为扶助动静备案,不妨运用汇编层上的属性applicationname和application action辨别指定用来维持汇编元素和运用步调举措典型的com+运用步调的名字。对于汇编备案的更多消息,参考: http://msdn.microsoft.com/library/en-us/cpguide/html/cpconregisteringserviced components.asp。 // the applicationname attribute specifies the name of the// com+ application which will hold assembly components[assembly : applicationname("dataservices")]// the applicationactivation.activationoption attribute specifies // where assembly components are loaded on activation// library : components run in the creator's process// server : components run in a system process, dllhost.exe[assembly: applicationactivation(activationoption.library)]下列代码段是一个叫作dataaccesscomponent的效劳组件,它运用com+构造字符串来赢得数据库贯穿字符串。 using system;using system.enterpriseservices;// the applicationname attribute specifies the name of the// com+ application which will hold assembly components[assembly : applicationname("dataservices")]// the applicationactivation.activationoption attribute specifies // where assembly components are loaded on activation// library : components run in the creator's process// server : components run in a system process, dllhost.exe[assembly: applicationactivation(activationoption.library)]// sign the assembly. the snk key file is created using the // sn.exe utility[assembly: assemblykeyfile("dataservices.snk")][constructionenabled(default="default dsn")]public class dataaccesscomponent : servicedcomponent{ private string connectionstring; public dataaccesscomponent() { // constructor is called on instance creation } public override void construct( string constructstring ) { // construct method is called next after constructor. // the configured dsn is supplied as the single argument this.connectionstring = constructstring; }}怎样运用sqldataadapter来检索多个行 底下的代码证明怎样运用sqldataadapter东西发出一个天生data set或datatable的吩咐。它从sql server northwind数据库中检索一系列产物目次。 using system.data;using system.data.sqlclient;public datatable retrieverowswithdatatable(){ using ( sqlconnection conn = new sqlconnection(connectionstring) ) { sqlcommand cmd = new sqlcommand("datretrieveproducts", conn); cmd.commandtype = commandtype.storedprocedure; sqldataadapter da = new sqldataadapter( cmd ); datatable dt = new datatable("products"); da.fill(dt); return dt; }}按下列办法运用sqladapter天生dataset或datatable: 创造sqlcommand东西起用保存进程,并把它与sqlconnection东西(表露的)或贯穿字符串(未表露)相接洽。 创造一个新的sqldataadapter东西,并把它sqlcommand东西相接洽。 创造datatable(大概dataset)东西。运用结构步调自变量定名datatable. 挪用sqldata adapter东西的fill本领,把检索的行变化到dataset或datatable中。 怎样运用sqldatareader检索多个行 下列代码说领会怎样运用sqldatareader本领检索多行: using system.io;using system.data;using system.data.sqlclient;public sqldatareader retrieverowswithdatareader(){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); sqlcommand cmd = new sqlcommand("datretrieveproducts", conn ); cmd.commandtype = commandtype.storedprocedure; try { conn.open(); // generate the reader. commandbehavior.closeconnection causes the // the connection to be closed when the reader object is closed return( cmd.executereader( commandbehavior.closeconnection ) ); } catch { conn.close(); throw; }}// display the product list using the consoleprivate void displayproducts(){ sqldatareader reader = retrieverowswithdatareader(); while (reader.read()) { console.writeline("{0} {1} {2}", reader.getint32(0).tostring(), reader.getstring(1) ); } reader.close(); // also closes the connection due to the // commandbehavior enum used when generating the reader}按下列办法运用sqldatareader检索多行: 创造用来实行保存的进程的sqlcommand东西,并把它与sqlconnection东西相接洽。 翻开链接。 经过挪用sqlcommand东西的excute reader本领天生sqldatareader东西。 从流中读取数据,挪用sqldatareader东西的read本领来检索行,并运用分门别类的存取步调本领(如getiut 32和get string本领)检索列的值。 实行读取后,挪用close本领。 怎样运用xmlreader检索多个行 不妨运用sqlcommand东西天生xmlreader东西,它供给对xml数据的鉴于流的前向考察。该吩咐(常常是一个保存的进程)必需天生一个鉴于xml的截止树立,它对于sql server2000常常是由带有灵验条件for xml的select状况构成。下列代码段说领会这种本领: public void retrieveanddisplayrowswithxmlreader(){ sqlconnection conn = new sqlconnection(connectionstring); sqlcommand cmd = new sqlcommand("datretrieveproductsxml", conn ); cmd.commandtype = commandtype.storedprocedure; try { conn.open(); xmltextreader xreader = (xmltextreader)cmd.executexmlreader(); while ( xreader.read() ) { if ( xreader.name == "products" ) { string stroutput = xreader.getattribute("productid"); stroutput += " "; stroutput += xreader.getattribute("productname"); console.writeline( stroutput ); } } xreader.close(); } catch { throw; } finally { conn.close(); }}上述代码运用了下列保存进程: create procedure datretrieveproductsxmlasselect * from products for xml autogo按下列办法检索xml数据: 创造sqlcommand东西起用天生xml截止树立的进程。(比方,运用select状况中的for xml条件)。把sqlcommand东西与一个链接相接洽。 挪用sqlcommand东西的executexmlreader本领,并把截止调配给前向东西xmltextreader。当不须要任何归来数据的鉴于xml的考证时,这是该当运用的最快典型的xmlreader东西。 运用xmltextreader东西的read本领读取数据。 怎样运用保存进程输入参数检索单个行 不妨挪用一个保存进程,它经过一种称做输入参数的办法不妨在单个行中归来检索数据项。下列代码段运用保存的进程检索产物的称呼和单价,该产物包括在northwind数据库中。 void getproductdetails( int productid, out string productname, out decimal unitprice ){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); // set up the command object used to execute the stored proc sqlcommand cmd = new sqlcommand( "datgetproductdetailsspoutput", conn ); cmd.commandtype = commandtype.storedprocedure; // establish stored proc parameters. // @productid int input // @productname nvarchar(40) output // @unitprice money output // must explicitly set the direction of output parameters sqlparameter paramprodid = cmd.parameters.add( "@productid", productid ); paramprodid.direction = parameterdirection.input; sqlparameter paramprodname = cmd.parameters.add( "@productname", sqldbtype.varchar, 40 ); paramprodname.direction = parameterdirection.output; sqlparameter paramunitprice = cmd.parameters.add( "@unitprice", sqldbtype.money ); paramunitprice.direction = parameterdirection.output; try { conn.open(); // use executenonquery to run the command. // although no rows are returned any mapped output parameters // (and potentially return values) are populated cmd.executenonquery( ); // return output parameters from stored proc productname = paramprodname.value.tostring(); unitprice = (decimal)paramunitprice.value; } catch { throw; } finally { conn.close(); }}按下列办法运用保存的进程输入参数检索单个行: 创造一个sqlcommand东西,并把它与sqlconnection东西相接洽。 经过挪用sqlcommand’s parameters汇合的add本领树立保存进程参数。缺省情景下,参数假设为输入参数,以是必需精确树立任何输入参数的目标。 提防 精确树立一切参数的目标是一次很好的熟习,囊括输出参数。 翻开贯穿。 挪用sqlcommand东西的executenonquery本领。它在输入参数(并潜伏地带有一个归来值)中。 运用value属性从符合的sqlparameter东西中检索输入参数。 封闭贯穿。 上述代码段起用了下列保存进程。 create procedure datgetproductdetailsspoutput@productid int,@productname nvarchar(40) output,@unitprice money outputasselect @productname = productname, @unitprice = unitprice from products where productid = @productidgo怎样运用sqldatareader检索单个行 不妨运用sqldatareader东西检索单个行,以及来自归来数据流的所需栏的值。这由下列代码证明: void getproductdetailsusingreader( int productid, out string productname, out decimal unitprice ){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); // set up the command object used to execute the stored proc sqlcommand cmd = new sqlcommand( "datgetproductdetailsreader", conn ); cmd.commandtype = commandtype.storedprocedure; // establish stored proc parameters. // @productid int input sqlparameter paramprodid = cmd.parameters.add( "@productid", productid ); paramprodid.direction = parameterdirection.input; try { conn.open(); sqldatareader reader = cmd.executereader(); reader.read(); // advance to the one and only row // return output parameters from returned data stream productname = reader.getstring(0); unitprice = reader.getdecimal(1); reader.close(); } catch { throw; } finally { conn.close(); }}按下列办法归来带有sqldatareader东西: 创造sqlcommand东西。 翻开贯穿。 挪用sqldreader东西的executereader东西。 运用sqldatareader东西的分门别类的存取步调本领检索输入参数--在这边是getstring和getdecimal. 上述代码段起用了下列保存进程: create procedure datgetproductdetailsreader@productid intasselect productname, unitprice from productswhere productid = @productidgo怎样运用executescalar单个项 executescalar本领是安排成用来归来单个值的考察。在归来多列或多行的考察事变中,executescalar只归来第一条龙的第一例。 下列代码证明怎样查问某个产物id的产物称呼: void getproductnameexecutescalar( int productid, out string productname ){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); sqlcommand cmd = new sqlcommand("lookupproductnamescalar", conn ); cmd.commandtype = commandtype.storedprocedure; cmd.parameters.add("@productid", productid ); try { conn.open(); productname = (string)cmd.executescalar(); } catch { throw; } finally { conn.close(); }}按下列办法运用execute scalar检索单个项: 创造挪用保存进程的sqlcommand东西。 翻开链接。 挪用executescalar本领,提防该本领归来东西典型。它包括检索的第一列的值,而且必需安排成符合的典型。 封闭链接。上述代码起用了下列保存进程: create procedure lookupproductnamescalar@productid intasselect top 1 productnamefrom productswhere productid = @productidgo怎样运用保存进程输入或归来的参数检索单个项 运用保存进程输入或归来的参数不妨查问单个值,下列代码说领会输入参数的运用: void getproductnameusingspoutput( int productid, out string productname ){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); sqlcommand cmd = new sqlcommand("lookupproductnamespoutput", conn ); cmd.commandtype = commandtype.storedprocedure; sqlparameter paramprodid = cmd.parameters.add("@productid", productid ); paramprodid.direction = parameterdirection.input; sqlparameter parampn = cmd.parameters.add("@productname", sqldbtype.varchar, 40 ); parampn.direction = parameterdirection.output; try { conn.open(); cmd.executenonquery(); productname = parampn.value.tostring(); } catch { throw; } finally { conn.close(); }}按下列办法运用保存进程的输入参数检索单个值: 创造挪用保存进程的sqlcommand东西。 经过把sqlparmeters增添到sqlcommand’s parameters汇合中树立任何输出参数和单个输入参数。 翻开链接。 挪用sqlcommand东西的execute nonquery本领。 封闭链接。 运用输入sqlparameter的value属性检索输入值。 上述代码运用了下列保存进程: create procedure lookupproductnamespoutput @productid int,@productname nvarchar(40) outputasselect @productname = productnamefrom productswhere productid = @productidgo下列代码证明怎样运用归来值决定能否生存特出行。从源代码的观点看,这与运用保存进程输入参数相一致,除去须要精确树立到parameterdirection.returnvalue的sqlparameter目标。 bool checkproduct( int productid ){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); sqlcommand cmd = new sqlcommand("checkproductsp", conn ); cmd.commandtype = commandtype.storedprocedure; cmd.parameters.add("@productid", productid ); sqlparameter paramret = cmd.parameters.add("@productexists", sqldbtype.int ); paramret.direction = parameterdirection.returnvalue; try { conn.open(); cmd.executenonquery(); } catch { throw; } finally { conn.close(); } return (int)paramret.value == 1;}按下列办法,不妨运用保存进程归来值查看能否生存特出行: 创造挪用保存进程的sqlcommand东西。 树立包括须要考察的行的重要要害字的输出参数。 树立单个归来值参数。把sqlparameter东西增添到sqlcommand’s parameter汇合中,并树立它到parameterdireetion.returnvalue的上面。 翻开链接。 挪用sqlcommand东西的executenonquery的本领. 封闭链接。 运用归来值sqlparameter的value属性检索归来值。 上述代码运用了下列保存进程: create procedure checkproductsp @productid intasif exists( select productid from products where productid = @productid ) return 1else return 0go怎样运用sqldatareader检索单个项。 经过挪用吩咐东西的executereader本领,不妨运用sqldatareader东西赢得单个输入值。这须要略微多少许的代码,由于sqldatareader read本领必需挪用,而后所需值经过读者群存取步调本领获得检索。sqldatareader东西的运用鄙人列代码中证明: bool checkproductwithreader( int productid ){ sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=northwind"); sqlcommand cmd = new sqlcommand("checkproductexistswithcount", conn ); cmd.commandtype = commandtype.storedprocedure; cmd.parameters.add("@productid", productid ); cmd.parameters["@productid"].direction = parameterdirection.input; try { conn.open(); sqldatareader reader = cmd.executereader( commandbehavior.singleresult ); reader.read(); bool brecordexists = reader.getint32(0) > 0; reader.close(); return brecordexists; } catch { throw; } finally { conn.close(); }}上述代码运用了下列保存进程: create procedure checkproductexistswithcount @productid intasselect count(*) from productswhere productid = @productidgo怎样源代码ado.net细工工作 下列代码证明怎样运用sql server. net数据供给器供给的工作扶助来养护工作的支金转帐操纵。该操纵在坐落同一数据库中的两个帐户之间变化支金。 public void transfermoney( string toaccount, string fromaccount, decimal amount ){ using ( sqlconnection conn = new sqlconnection( "server=(local);integrated security=sspi;database=simplebank" ) ) { sqlcommand cmdcredit = new sqlcommand("credit", conn ); cmdcredit.commandtype = commandtype.storedprocedure; cmdcredit.parameters.add( new sqlparameter("@accountno", toaccount) ); cmdcredit.parameters.add( new sqlparameter("@amount", amount )); sqlcommand cmddebit = new sqlcommand("debit", conn ); cmddebit.commandtype = commandtype.storedprocedure; cmddebit.parameters.add( new sqlparameter("@accountno", fromaccount) ); cmddebit.parameters.add( new sqlparameter("@amount", amount )); conn.open(); // start a new transaction using ( sqltransaction trans = conn.begintransaction() ) { // associate the two command objects with the same transaction cmdcredit.transaction = trans; cmddebit.transaction = trans; try { cmdcredit.executenonquery(); cmddebit.executenonquery(); // both commands (credit and debit) were successful trans.commit(); } catch( exception ex ) { // transaction failed trans.rollback(); // log exception details . . . throw ex; } } }}怎样运用transact-sql实行工作 下列保存进程说领会怎样在transact-sql进程内实行工作的支金变化操纵。 create procedure moneytransfer@fromaccount char(20),@toaccount char(20),@amount moneyasbegin transaction-- perform debit operationupdate accountsset balance = balance - @amountwhere accountnumber = @fromaccountif @@rowcount = 0begin raiserror('invalid from account number', 11, 1) goto abortenddeclare @balance moneyselect @balance = balance from accountswhere accountnumber = @fromaccountif @balance < 0begin raiserror('insufficient funds', 11, 1) goto abortend-- perform credit operationupdate accounts set balance = balance + @amount where accountnumber = @toaccountif @@rowcount = 0begin raiserror('invalid to account number', 11, 1) goto abortendcommit transactionreturn 0abort: rollback transactiongo该保存进程运用begin transaction, commit transaction,和rollback transaction状况细工遏制工作。 怎样源代码工作性的.net类 下述例子是三种效劳性的net类,它们摆设或用来机动工作。每个类都带有transaction属性,它的值将确定能否启用新工作流大概东西能否共享立即挪用步调的数据流。那些元素一道处事来实行钱庄支金变化。transfer类摆设有requiresnew工作属性,而debit和credit类摆设有required属性。如许,在运转的功夫三个东西共享同一个工作。 using system;using system.enterpriseservices;[transaction(transactionoption.requiresnew)]public class transfer : servicedcomponent{ [autocomplete] public void transfer( string toaccount, string fromaccount, decimal amount ) { try { // perform the debit operation debit debit = new debit(); debit.debitaccount( fromaccount, amount ); // perform the credit operation credit credit = new credit(); credit.creditaccount( toaccount, amount ); } catch( sqlexception sqlex ) { // handle and log exception details // wrap and propagate the exception throw new transferexception( "transfer failure", sqlex ); } }}[transaction(transactionoption.required)]public class credit : servicedcomponent{ [autocomplete] public void creditaccount( string account, decimal amount ) { sqlconnection conn = new sqlconnection( "server=(local); integrated security=sspi"; database="simplebank"); sqlcommand cmd = new sqlcommand("credit", conn ); cmd.commandtype = commandtype.storedprocedure; cmd.parameters.add( new sqlparameter("@accountno", account) ); cmd.parameters.add( new sqlparameter("@amount", amount )); try { conn.open(); cmd.executenonquery(); } catch (sqlexception sqlex) { // log exception details here throw; // propagate exception } }}[transaction(transactionoption.required)]public class debit : servicedcomponent{ public void debitaccount( string account, decimal amount ) { sqlconnection conn = new sqlconnection( "server=(local); integrated security=sspi"; database="simplebank"); sqlcommand cmd = new sqlcommand("debit", conn ); cmd.commandtype = commandtype.storedprocedure; cmd.parameters.add( new sqlparameter("@accountno", account) ); cmd.parameters.add( new sqlparameter("@amount", amount )); try { conn.open(); cmd.executenonquery(); } catch (sqlexception sqlex) { // log exception details here throw; // propagate exception back to caller } }}合作家 特殊感动下列撰稿者和审阅校对者: bill vaughn, mike pizzo, doug rothaus, kevin white, blaine dokter, david schleifer, graeme malcolm(实质大师), bernard chen(西班牙人), matt drucke(融合)和steve kirk. 读者群有怎么办的题目、指摘和倡导?对于正文的反应消息,请发e-mail至devfdbck®microsoft.com。 你蓄意进修并运用.net的宏大功效吗?与微软本领重心的本领大师一道处事,进修开拓

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.