ASP.NET网站制作之DataSet的数据并发非常处置
可怜的程序员,还是逃不出移植的命运!数据|非常处置 择要:ADO.NET为进步数据麋集型(data-intensive)使用程序的功能、简化这类程序的创建历程供应了多种手艺。数据集(DataSet)作为ADO.net工具模子的标记,作为一个微型的、不毗连(disconnected)的数据源的正本供应服务。固然利用数据集经由过程削减对数据库服务器的高消费的会见而进步了功能,可是它也带来了多个用户试图同时会见不异数据的大概性,由此引发数据并发性非常(dataconcurrencyexception)。本文查询拜访了数据并发性非常面前的一般原因,先容懂得决这些成绩的手艺。 把数据会见层晋级到ADO.NET有良多优点,个中之一是利用外部数据集工具。数据集工具基础上是一个不毗连的、内存中的数据库的拷贝。数据集工具包括一个大概多个数据表(DataTable),每一个数据表一样平常对应于数据库中的一个表。数据集供应了良多优点,但也带来一些成绩,出格是大概碰到与数据并发性非常相干的成绩。我创建了一个复杂的WindowsForms主顾服务使用程序,用它来注释该成绩的潜伏的缺点。本文我将先容该使用程序并演示如何办理它所引发的数据并发性成绩。本文创建的主顾服务使用程序示例是利用VisualBasic.NET和SQLServer2000创建的,可是因为微软.NET框架组件是言语有关(language-agnostic)的,因而任何与.NET框架组件兼容的言语都可使用。一样,因为数据集工具笼统了数据源,数据源的实践实行其实不主要;不管上层的数据源是SQLServer、当地XML文件大概从一个服务中检索到的数据,数据并发性非常一样会呈现。
数据集的利害
数据集供应了良多优点,比方比起数据库条理,它强化了内存中的完全性划定规矩。数据集工具能够界说和强化表之间的干系和列的束缚,确保利用的贸易划定规矩对数据库没出缺陷。经由过程数据库笼统,你能创建单个代码汇合会见数据集工具而不用思索添补该数据集的源数据。上层的数据源大概是SQLServer、Oracle乃至XML文件。不管上层数据源是甚么,代码利用不异的办法与数据集交互。这使你能改动上层数据源而不改动代码。
可是利用数据集的最年夜优点是进步了功能。由于数据集与上层数据库断开,代码将更少作数据库的挪用,明显地进步了功能。你能向数据集的多个数据表中增加新行、考证每行的无效性和参照完全性。数据适配器(DataAdapter)把数据集毗连到上层数据库,能利用一条命令更新上层数据库。每一个表中的一切新行都利用命令到场,以确保一切增加到数据库的行都是无效的。
功能的最优化是有价值的。由于数据集工具与上层数据库断开,常常无机会呈现数据没有超期(outofdate)的情形。由于数据集不保留举动数据,只保留事先添补数据集的举动数据的一个快照,与数据并发性相干的成绩就会呈现。数据并发性成绩呈现在多个用户会见不异的数据而且任何一个用户没有别的用户的信息就可以更新数据。这就呈现了一个用户偶尔更新数据而不晓得那些数据已改动了,不是他在程序中看到的了。侥幸的是数据集工具具有捕捉数据并发性成绩的内建(built-in)撑持,因而使用程序能准确地作出反响。
示例程序
一个假造的公司利用该主顾服务使用程序创建主顾定单,更新主顾的团体信息。有良多客户发卖代表(CSR)在桌面上利用该使用程序。CSR利用德律风猎取定单,从主顾那儿搜集团体信息和付出信息。主顾纪录保留在数据库中以进步转头客处置定单的速率,CSR接着创建一个定单并把产物项增加上往,指定命量和今朝的代价,一切的信息搜集后,CSR点击PlaceOrder按钮,向数据库中拔出主顾和定单纪录。
CSR也利用使用程序实行经由过程电子大概迟缓的邮件发送给公司的哀求。这些哀求在CSR间匀称分隔,在天天凌晨发送给他们,CSR经由过程德律风实行那些哀求。体系计划要进步哀求的完成速率,一切的主顾在CSR之间共享。主顾的每一个哀求,不管经由过程德律风大概邮件,都被分歧的CSR处置,增添了产生数据并发性成绩的时机。
为了进步功能,使用程序在内存中坚持了一个用主顾和定单信息添补的数据集工具。由于良多雇员同时利用该使用程序,就会有很多举动数据的不毗连的快照,它们都在雇员的事情站上。一切主顾的保护、定单输出和定单保护都利用名为dsAllData的数据集工具。是创建dsAllData的代码,它是全局模块的一部分,因而使用程序中的一切窗体都能利用它。
ConstconnString="server=localhost;database=northwind;uid=sa;pwd="
PublicconnCustSVCAsSqlClient.SqlConnection
PublicdaCustomerAsSqlClient.SqlDataAdapter
PubliccbCustomerAsSqlClient.SqlCommandBuilder
PublicdaOrdersAsSqlClient.SqlDataAdapter
PubliccbOrdersAsSqlClient.SqlCommandBuilder
PublicdaOrderDetailAsSqlClient.SqlDataAdapter
PubliccbOrderDetailAsSqlClient.SqlCommandBuilder
PublicdsAllDataAsDataSet
PublicSubMain()
connCustSvc=NewSqlClient.SqlConnection(connString)
daCustomer=NewSqlClient.SqlDataAdapter("SELECT*FROMCustomer",connCustSvc)
cbCustomer=NewSqlClient.SqlCommandBuilder(daCustomer)
daOrders=NewSqlClient.SqlDataAdapter("SELECT*FROMOrders",connCustSvc)
cbOrders=NewSqlClient.SqlCommandBuilder(daOrders)
daOrderDetail=NewSqlClient.SqlDataAdapter("SELECT*FROMOrderDetail",connCustSvc)
cbOrderDetail=NewSqlClient.SqlCommandBuilder(daOrderDetail)
dsAllData=NewDataSet()
daCustomer.MissingSchemaAction=MissingSchemaAction.AddWithKey
daCustomer.Fill(dsAllData,"Customer")
daOrders.MissingSchemaAction=MissingSchemaAction.AddWithKey
daOrders.Fill(dsAllData,"Orders")
dsAllData.Tables("Orders").Columns("Total").DefaultValue=0
daOrderDetail.MissingSchemaAction=MissingSchemaAction.AddWithKey
daOrderDetail.Fill(dsAllData,"OrderDetail")
Application.Run(NewfrmCustomerMaintenance())
EndSub
创建dsAllData的代码创建了一个空的数据集工具、三个数据适配器(DataAdapter)和三个命令机关器(CommandBuilder)。每一个数据适配器在得当的表上实行一个复杂的"SELECT*"操纵,而命令机关器用必要的残剩信息添补数据集,使它有拔出(insert)、更新(update)和删除(delete)的才能。主程序利用数据适配器工具和一切三个表中的数据添补dsAllData,接着利用CustomerMaintenance窗体入手下手使用程序。
显现的是CustomerMaintenance屏幕,它有一个绑定到dsAllData的Customers数据表的DataGrid工具。这个复杂的表格同意CSR编纂主顾的恣意基础属性。由于该表格绑定到了Customers数据表,表格中的任何改动都将主动存储到数据表中。dsAllData将保留这些值,直到CSR点击SaveChanges按钮明白地告知窗体更新上层数据源为止。
为了输出定单,利用中的代码创建了几个新行并增加到dsAllData中。起首创建一个Order纪录,接着在数据表OrderDetail中为定单的每一个项创建几个纪录。当一切必需的行增加到dsAllData后,一个得当的数据适配器的Update办法挪用将用新行更新上层数据源。
PrivateSubCreateOrder()
DimdrAsDataRow
dr=dsAllData.Tables("Orders").NewRow
Withdr
.Item("DateOrdered")=Now
.Item("CustomerID")=1
.Item("ShipToAddress")="123Main"
.Item("ShipToCity")="KansasCity"
.Item("ShipToState")="MO"
.Item("ShipToZip")="12345"
EndWith
dsAllData.Tables("Orders").Rows.Add(dr)
AddOrderDetail(dr.Item("ID"),1,1,9.99)
AddOrderDetail(dr.Item("ID"),2,2,4.99)
daOrders.Update(dsAllData.Tables("Orders"))
daOrderDetail.Update(dsAllData.Tables("OrderDetail"))
EndSub
PrivateSubAddOrderDetail(ByValOrderIDAsInteger,_
ByValProductIDAsInteger,ByValQuantityAsInteger,_
ByValPriceAsSingle)
DimdrAsDataRow
dr=dsAllData.Tables("OrderDetail").NewRow
Withdr
.Item("OrderID")=OrderID
.Item("ProductID")=ProductID
.Item("Quantity")=Quantity
.Item("Price")=Price
EndWith
dsAllData.Tables("OrderDetail").Rows.Add(dr)
EndSub
由于CSR同时利用使用程序和更新主顾信息,因而仿佛任什么时候候一个CSR看到的都是过时的信息。为了避免这类征象,使用程序的计划师决意dsAllData的数据缓存要每隔30分钟革新一次,以确保CSR一般看到准确信息。使用程序计划得很细心,以确保数据革新只在余暇时段举行,如许它才不影响功能。数据集革新因而会比30分钟长一点,这依附于CSR的举动。
该使用程序的数据模子很复杂()。它利用SQLServer2000存储,只包括三个表,主顾表、定单表、每一个定单的细节表,并界说了得当的主键和干系以确保参照的完全性。别的,在OrderDetail上界说了一个触发器来更新Orders表的Total列。每次拔出、更新大概删除一个OrderDetail纪录,挪用触发器盘算该定单的最初发卖值,并更新Orders表的得当的行。是trg_UpdateOrderTotal触发器的代码:
CREATETRIGGERtrg_UpdateOrderTotalON.
FORINSERT,UPDATE,DELETE
AS
DECLARE@OrderIDint
SELECT@OrderID=OrderIDFROMInserted
IF@OrderIDISNULL
SELECT@OrderID=OrderIDFROMDeleted
UPDATEOrders
SETTotal=
(
SELECTSum(Price*Quantity)
FROMOrderDetail
WHEREOrderID=@OrderID
)
WHEREID=@OrderID
第一个数据并发性非常
该主顾服务使用程序利用了几个月没有任何成绩,可是俄然发生了一个没有处置的非常DBConcurrencyException。本段我将注释招致该非常的情况。
第一个利用该使用程序的主顾发卖服务职员Joe翻开使用程序。这将初始化将数据载进数据集dsAllData并按每30分钟一次的周期来革新数据。Joe的收件箱中有一堆文件,包含主顾传真、邮寄大概经由过程电子邮件发送的变动哀求。他入手下手处置变动哀求,可是常常被德律风定单中止。
其间,第二个客户发卖服务职员Sally抵达办公室并翻开了她的使用程序实例。Sally的使用程序实例也初始化从SQLServer中载数据,包含Joe所作的更新。Sally也接到了一个主顾改动德律风号码的哀求。该主顾先前用电子邮件发送了地点的改动情形,可是在当时不晓得他的新德律风号码,如今要更新纪录了。Sally利用CustomerMaintenance屏幕更新主顾的德律风号码。当Sally改动DataGrid中的德律风号码时,新号码存储在dsAllData中。当Sally确认别的的主顾信息后,她意想到原地点的改动还没有处置,因而她更新那些信息并点击SaveChanges按钮,将新数据发送到SQLServer数据库。
Joe正在处置不异主顾的原始哀求。当他翻开CustomerMaintenance屏幕时,使用程序从缓存数据集工具中读进信息。由于Sally更新主顾地点时,Joe的使用程序没有主动与数据库同步,因而他的CustomerMaintenance屏幕仍旧显现旧地点。Joe利用电子邮件供应的新信息更正了DataGrid中显现的信息,并点击SaveChanges按钮。如许操纵后呈现了一个毛病信息"并发性妨碍:更新命令影响了0个纪录(Concurrencyviolation:theUpdateCommandaffected0records)",使用程序溃散了。在Joe再次翻开使用程序时,他发明地点已更新了,以为他的变动在使用程序溃散前已完成了。上面就是成绩的代码行:
PrivateSubbutSave_Click(ByValsenderAsSystem.Object,_
ByValeAsSystem.EventArgs)
daCustomer.Update(dsAllData.Tables("Customer"))
EndSub
实践的非常是DBConcurrencyException范例发生的,它是数据适配器工具外部创建的特定功效的了局(见)。该数据适配器计划为把数据添补到不毗连的工具(比方数据集),如许它在实行更新前能主动地反省数据寻觅改动。假如上层数据被改动了,数据适配器将激发一个DBConcurrencyException非常而不是实行更新。
实行完全性反省是相称间接的,它进步了数据表工具的功能,使它可以坚持多个数据汇合。当数据第一次载进数据表时,数据表中的一切数据行(DataRow)的DataRowVersion属性设置为原始的(Original)。当修正了数据行中的一列时,该行就被复制一份并标志为以后的(Current),标志为原始的行仍旧没有改动。厥后的一切对该数据的变动都仅仅影响以后行。当为一个数据表(大概一个数据会合的多个数据表)实行数据适配器的更新办法时,它反复一切确当前行来决意要发送给上层数据源的更新语句。作为DataRowVersion属性的增补,数据行有一个用于辨认行中数据形态的RowState属性。它的大概值为Unchanged、Added、Modified、Deleted和Detached。
在决意上层数据中的哪些行必要更新后,数据适配器dsCustomer创建更新SQLServer数据库所必要的SQL语句。在中我利用数据集和命令机关器工具来创建必要的INSERT、UPDATE和DELETE语句。命令机关器工具创建的UPDATE语句利用DataRowVersion值为Original的数据行正本来辨认和更新数据库中的得当行。这就是说,作为利用主键值复杂地辨认准确行的取代,命令机关器创建一个SQL语句来查找与数据会合存储的原始值正确婚配的行。上面的代码是创建的用于更新主顾德律风号码的UPDATE语句示例:
UPDATECustomerSETPhone=@p1
WHERE((ID=@p2)AND((FirstNameISNULLAND@p3ISNULL)
OR(FirstName=@p4))
AND((LastNameISNULLAND@p5ISNULL)OR(LastName=@p6))
AND((AddressISNULLAND@p7ISNULL)OR(Address=@p8))
AND((Address2ISNULLAND@p9ISNULL)OR(Address2=@p10))
AND((CityISNULLAND@p11ISNULL)OR(City=@p12))
AND((StateISNULLAND@p13ISNULL)OR(State=@p14))
AND((ZipISNULLAND@p15ISNULL)OR(Zip=@p16))
AND((PhoneISNULLAND@p17ISNULL)OR(Phone=@p18)))
该UPDATE语句利用参数而不是实践值,可是你能看到行中每列是如何反省的。
辨认了正确的行和上层数据库中的原始值后,数据适配器就能够平安地更新行了。可是,假如自从数据表被添补后数据库中某行的某个列改动了,UPDATE语句将失利,由于数据库中没有与WHERE前提中的尺度婚配的行了。数据适配器决意UPDATE是不是乐成很复杂,只必要复杂地反省数据库中被更新的行的实践数目。假如没有行被更新,那末上层数据必定被改动或删除,就发生一个数据并发性非常。这就注释了Joe试图更新主顾德律风号码时吸收到的有点含混的毛病动静:数据适配器反省到的实践毛病不是上层数据改动了,而是没有纪录被更新,标记着上层数据一定被改动了。
办理办法
有两种路子办理DBConcurrencyException成绩。第一种是确保它永不重现:我能够删除中代码利用的SqlCommandBuilder工具,把它们改换为数据适配器工具的UpdateCommand属性的SqlCommand工具。我将在CommandText属性中创建带有WHERE前提的SQL语句,只举行主键而不是一切列的过虑。如许将扫除一切并发性成绩(假定主键不会改动)。
可是这类手艺带来了几个成绩。起首,很分明要更多的代码,由于我还得为每一个数据适配器的InsertCommand和DeleteCommand属性创建SqlCommand工具。别的,假如上层数据库提要(schema)产生了变化,这些硬编码将带来新毛病。假如利用SqlCommandBuilder工具,使用程序在运转时决意数据库提要,承受任何改动,响应地创建SQL语句。这不是办理并发性成绩,而是完整的制止了该成绩,利用户在不知不觉中掩盖了别人的变动。
Try
daCustomer.Update(dsAllData.Tables("Customer"))
CatchdbcExAsData.DBConcurrencyException
DimdResultAsDialogResult
dResult=MessageBox.Show(messageString,_
"DataConcurrencyExceptionOccurred",_
MessageBoxButtons.YesNoCancel,MessageBoxIcon.Error,_
MessageBoxDefaultButton.Button1,_
MessageBoxOptions.DefaultDesktopOnly)
IfdResult=DialogResult.YesThen
两个选择:添补全部表大概革新该行
daCustomer.Fill(dsAllData.Tables("Customer"))
UpdateRow("Customer",dbcEx.Row.Item("ID"))
ElseIfdResult=DialogResult.NoThen
保留新行的拷贝
DimdrCopyAsDataRow,drCurrentAsDataRow
drCopy=dsAllData.Tables("Customer").NewRow()
DimdcAsDataColumn
drCurrent=dsAllData.Tables("Customer").Rows.Find(dbcEx.Row.Item("ID"))
ForEachdcIndrCurrent.Table.Columns
Ifdc.ReadOnly=FalseThen
drCopy.Item(dc.ColumnName)=drCurrent.Item(dc.ColumnName)
Next
从数据库中猎取以后值
UpdateRow("Customer",dbcEx.Row.Item("ID"))
如今恢复用户输出的值并再次保留
ForEachdcIndrCurrent.Table.Columns
Ifdc.ReadOnly=FalseThen
drCurrent.Item(dc.ColumnName)=drCopy.Item(dc.ColumnName)
Next
daCustomer.Update(dsAllData.Tables("Customer"))
EndIf
EndTry
Try...Catch块捕获了DBConcurrencyException并给用户显现一个标识该毛病的动静窗口,给用户供应一个选择(所示)。如许我辨认已呈现了一个并发性毛病并有两个选择:我能够检索上层数据并显现给用户,强迫他们再次作修正,大概我能复杂地利用该用户指定的改动掩盖上层数据。
PrivateSubUpdateRow(ByValTableNameAsString,ByValIDAsInteger)
猎取到特定行的援用
DimdrAsDataRow=dsAllData.Tables(TableName).Rows.Find(ID)
创建命令更新猎取新的上层数据
DimcmdAsNewSqlClient.SqlCommand("SELECT*FROM"&TableName"WHEREID="&ID.ToString(),connCustSVC)
翻开毗连并创建数据读取器(DataReader)
connCustSvc.Open()
DimrdrAsSqlClient.SqlDataReader=cmd.ExecuteReader()
rdr.Read()
将新数据从数据库复制到数据行
DimdcAsDataColumn
ForEachdcIndr.Table.Columns
Ifdc.ReadOnly=FalseThen_
dr.Item(dc.ColumnName)=rdr.Item(dc.ColumnName)
Next
承受数据行中的改动
dr.AcceptChanges()
connCustSvc.Close()
EndSub
假如用户决意检察新的上层改动并保持他们的变动,你只必要复杂地革新存储在Customer数据表中的数据。由于DataGrid绑定到数据表,该表格将主动地显现新数据。为了革新数据,你有两种选择:第一种是利用数据适配器daCustomer的Fill办法来复杂地添补全部数据表。固然这类手艺可以完成,可是它的消费太年夜,由于原本你只必要革新一行。我创建了一个叫UpdateRow的程序,它仅仅读进有成绩的行的数据()。利用UpdateRow程序时要注重我已在参数汇合中界说了被找到的数据行是单个的、整型关头字的列,假如该表有分歧数据范例大概复合键,你必需重载UpdateRow来处置特定键的需求。在数据行和/或数据表用以后数据革新后,DataGrid在引发并发性非常的行上显现一个小Error图标。
用户的另外一个选择是疏忽对上层数据库的变动,强制他的改动失效。有多种办法能够完成该功效。第一种是SQLServer数据库上间接实行一个SQL语句来使数据表中的数据同步。只管这类办法能够完成,可是它请求你在数据库变动时为重写一切的SQL语句。利用这类手艺编写的SQL是利用的特定命据库版本的硬编码(hard-coded),丧失了数据适配器和数据集工具供应的笼统性。
更好的选择是利用我后面所写的UpdateRow程序而且同意数据适配器处置更新。中的代码起首创建了含有新的变动的数据行的拷贝,接着挪用UpdateRow程序从数据库中取得新数据。挪用UpdateRow历程是需要的,如许你在试图再次实行更新时才不会吸收到并发性非常。该代码接着迭代数据行中一切的列,利用用户供应的值更新比来检索到的值。最初,利用数据适配器更新上层数据库。
这些代码办理办法都有一些潜伏的成绩。起首,默许情形下数据适配器的Update办法在第一个并发性非常时就会失利,不处置前面的数据行。这会招致数据的部分更新大概几个并发性非常,每个由用户独自处置。中的代码显现了另外一个潜伏的非常,在强制用户的变动到上层数据库的时分。有很小的时机呈现另外一个用户在挪用UpdateRow程序和实行daCustomer的Update办法之间变动了上层数据库。这将发生一个未处置的DBConcurrencyException。一种大概的办理办法是把Update办法放进Try...Catch块,可是第二个Catch代码大概与第一个类似,而且能潜伏的发生它本人的并发性非常,就必要更多的Try...Catch块,直到无量。更好的办理办法是将这段代码放进一个自力的在多个并发性非常产生的情形下能够挪用的程序中。
利用SQLServer触发器
为该公司开辟主顾服务使用程序的职员已处置好Joe更新主顾信息时吸收到的DBConcurrencyException非常的代码,使用程序事情又得很好了--直到下战书Sally试图输出一个定单为止。
Sally接到一个主顾的定单德律风。该主顾信息已在数据库中了,因而Sally利用定单的基础信息包含邮寄地点。接着她翻开OrderDetails屏幕并给定单增加了两个项目。每一个OrderDetail纪录包含OrderID、ProductID、Quantity和Price。定单填完后,Sally点击PlaceOrder按钮把定单拔出数据库。我经由过程为OrderDetail纪录增加硬编码值简化了代码(如所示)。
定单乐成地拔出和数据库,可是Sally接到一个提醒,显现一个项没有货了,定单不克不及在两周内发货。该主顾意想到包裹投递时他不在城里,就扣问是不是能够变动发货地点。Sally在利用OrderMaintenance屏幕前已变动了定单信息,因而她说乐于协助。她翻开得当的屏幕并为该主顾改动发货地点。可是她点击SaveChanges按钮时,看到了一个与Joe类似的毛病对话框,使用程序溃散了。
了解为何发生DBConcurrencyException的关头在于上层数据库。回忆中我在OrderDetail表上设置了一个触发器,一切的INSERTS、UPDATES和DELETES都将挪用它。trg_UpdateOrderTotal经由过程盘算Order中每一个OrderDetail行的数目乘以代价更新定单的总代价。当Sally创建一个有两个项的定单时,使用程序起首向Orders中拔出一个新行,接着向OrderDetail拔出两个新行。在每一个OrderDetail纪录创建后,挪用触发器更新Order纪录的Total列。可是这个值只在数据库中发生而且不会传送到使用程序。实践上,中的代码没有指定Total,由于在的代码中已指定了一个默许值。接着默许值0跟着新的Orders纪录传送进SQLServer,该值在定单创建时是准确的。数据库接着更新Total列,可是使用程序中的数据表仍旧利用0作为定单总价。当Sally试图更新Order纪录时,数据适配器以为Total列的值已改动了并发生一个DBConcurrencyException非常。
这儿的圈套是已往当Sally已更新Order纪录时,可巧自从最初一次数据主动革新产生后,她没有更新方才创建的新定单。在创建每一个定单30分钟内,dsAllData数据集工具被革新,它将利用准确的算计值更新Orders数据表。任安在数据主动更新(大概使用程序从头启动)后作的更新将按估计的情况事情。
这个成绩的办理办法与后面的成绩类似:革新用户看到的数据。可是我可以更自动,不是守候并发性非常产生。我能在创建OrderDetail纪录后,主动革新每个Orders数据行。我能变动中的代码,使它包括一个UpdateRow程序的挪用,在挪用daOrderDetail的Update办法后指定Orders中的行。SQLServer将一般完成该触发器,可是你不克不及依附它,因而开辟者大概会增加一个工夫提早,如许触发器有充足的工夫完成。
结论
ADO.NET数据集工具的不毗连特征供应了很高的功能,也给使用程序带来了数据并发性范例的毛病。懂得这些毛病如何和为何呈现将同意你很好地捕获和处置这类毛病,给使用程序增添另外一个条理的撑持。这给用户保护上层数据的完全性更多的选择。陪伴着使用程序进一步迁徙到互联网和外部网,用户成倍增添,并发性成绩的处置面对更年夜的应战。ADO.net为办理该成绩供应了一切的需要工具。
完全不一样的。.net其实我也说不太清,.net可以把他理解为跟J2EE相对的工具。c++主要做系统相关的开发你要学.net的话就应该学C#。(其实微软在.NET平台上也考虑了给C++留一个地位。 可以通过在现有ASP应用程序中逐渐添加ASP.NET功能,随时增强ASP应用程序的功能。ASP.NET是一个已编译的、基于.NET的环境,可以用任何与.NET兼容的语言(包括VisualBasic.NET、C#和JScript.NET.)创作应用程序。另外,任何ASP.NET应用程序都可以使用整个.NETFramework。开发人员可以方便地获得这些技术的优点,其中包括托管的公共语言运行库环境、类型安全、继承等等。 弱类型造成潜在的出错可能:尽管弱数据类型的编程语言使用起来回方便一些,但相对于它所造成的出错几率是远远得不偿失的。 代码逻辑混乱,难于管理:由于ASP是脚本语言混合html编程,所以你很难看清代码的逻辑关系,并且随着程序的复杂性增加,使得代码的管理十分困难,甚至超出一个程序员所能达到的管理能力,从而造成出错或这样那样的问题。 但是java靠开源打出的一片天地,特别是在微软的垄断下能打开今天的局面还是有它的生命力的。 ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。 逐步缩小出错代码段的范围,最终确定错误代码的位置。 微软又推出ASP.NET。这不是ASP的简单升级,而是全新一代的动态网页实现系统,用于一台WEB服务器建立强大的应用程序。是微软发展的新体系结构.NET的一部分,是ASP和.NET技术的结合。
页:
[1]