成長空間

          MiLife

          常用鏈接

          統計

          積分與排名

          Automation Testing Development

          最新評論

          #

          單點登陸 single sign-on

              只有注冊用戶登錄后才能閱讀該文。閱讀全文

          posted @ 2007-07-25 18:44 Picasso 閱讀(69) | 評論 (0)編輯 收藏

          ADO and ADO.net

          ADO是什么,它是如何操作數據庫的?

            答:ADO的全名是ActiveX Data Object(ActiveX數據對象),是一組優化的訪問數據庫的專用對象集,它為ASP提供了完整的站點數據庫解決方案,它作用在服務器端,提供含有數據庫信息的主頁內容,通過執行SQL命令,讓用戶在瀏覽器畫面中輸入,更新和刪除站點數據庫的信息。

            ADO主要包括Connection,Recordset和Command三個對象, 它們的主要功能如下:

            ·Connection對象:負責打開或連接數據庫文件;
            ·Recordset對象:存取數據庫的內容;
            ·Command對象:對數據庫下達行動查詢指令,以及執行SQL Server的存儲過程。

          使用Recordset對象和Command對象來訪問數據庫的區別在哪里?

            答:Recordset對象會要求數據庫傳送所有的數據,那么數據量很大的時候就會造成網絡的阻塞和數據庫服務器的負荷過重,因此整體的執行效率會降低。
          利用Command對象直接調用SQL語句,所執行的操作是在數據庫服務器中進行的,顯然會有很高的執行效率。特別是在服務器端執行創建完成的存儲過程,可以降低網絡流量,另外,由于事先進行了語法分析,可以提高整體的執行效率。


          什么是ADO.NET架構

          如今大部分的應用程序都需要后臺的數據庫來為其提供大量的數據來源,而應用程序與數據庫之間的交流稱為數據訪問。而ASP.NET則使用ADO.NETActive X Data Object)作為數據的訪問與操作的協議,從而使得我們可以在Internet上操作這些數據。

          ADO.NET的數據訪問分為兩大部分:數據集(DataSet)與數據提供源(Data Provider,我并不清楚中文該怎么翻譯,就叫它數據提供源好了,不要和“數據源”—Data Source搞混)

           

          數據集:

          數據集是一個非在線,完全由內存表示的一系列數據,可以被看作一份本地磁盤數據庫中部分數據的拷貝。數據集完全駐留內存,可以被獨立于數據庫地訪問或者修改。當數據集的修改完成后,更改可以被再次寫入數據庫,從而保留我們所做過的更改。數據集中的數據可以由任何數據源(Data Source)提供,比如SQL Server或者Oracle

           

          數據提供源:

          數據提供源用于提供并維護應用程序與數據庫之間的連接。

          數據提供源是一系列為了提供更有效率的訪問而協同工作的組件。如今微軟在ADO.NET中提供了兩組數據提供源,一組叫做SQL Data ProviderSQL數據提供源),用于提供應用程序與SQL Server 7.0或者更高版本的訪問。另一組叫做OleDb DataProviderObject Linking and Embedding DataBase DataProvider),可以允許我們訪問例如Oracle 之類的第三方數據源。

          每組數據提供源中都包含了如下四個對象:

          Connect對象提供了對數據庫的連接。

          Command對象可以用來執行命令。

          DataReader對象提供了只讀的數據記錄集。

          DataAdapter對象提供了對數據集更新或者修改的操作。

           

          總體來說,使用ADO.NET訪問數據可以被概括為以下步驟:

          首先應用程序創建一個Connect對象用來建立與數據庫之間的連接。然后Command對象提供了執行命令的接口,可以對數據庫執行相應的命令。當命令執行后數據庫返回了大于零個數據時,DataReader會被返回從而提供對返回的結果集的數據訪問。或者,DataAdapter可以被用來填充數據集,然后數據庫可以由Command對象或者DataAdapter對象進行相應的更改。

          具體來看數據提供源的四種對象

           

          Connect 對象

          Connect對象用來提供對數據庫的連接,Microsoft Visual Studio .Net中微軟提供了兩種Connect對象,分別為SqlConnection對象,用來提供對SQL Server 7.0或更高版本的連接,同時還有OleDbConnection對象,用來提供對Access與其他第三方數據庫的連接。

           

          Command 對象

          同樣,Command對象分為兩組,SqlCommandOleDbCommandCommand對象被用來執行針對數據庫的命令,比如執行數據庫的存儲過程(Stored Procedure)SQL命令,或者直接返回一個完整的表。Command對象提供三種方法(Methods)用來執行上述操作。

          ExecuteNonQuery用來執行一個不需返回數據的命令,比如表的插入,更新或者刪除操作。

          ExecuteScalar返回從一個查詢得到的單獨的值。

          ExecuteReader用來返回一個從DataReader來的結果集。

           

          DataReader對象

          DataReader提供了forward-only, read-only, connected stream的結果集。

          這里的forward-only表示數據只能夠向前,如果我們訪問了一條數據后想要再次訪問這條數據就必須重新開始。

          Read-only表示只讀,不能夠對結果集進行操作。

          Connected stream表示DataReader對象是面向流連接的。所謂的流可以把它看作是管道,這邊放進去東西那邊就可以得到,實際上TCP協議就是面向連接的流協議。

          不同于其他的三種對象,DataReader不能夠被用戶直接創建,必須也只能由ExecuteReader返回。

          SqlCommand.ExecuteReader返回SqlDataReader

          同理,OleDbCommand.ExecuteReader返回OleDbDataReader

          需要注意的是,DataReader對應用程序提供行級訪問(每次只能訪問數據的一行),當你需要多行的時候就需要多次的訪問這個對象。這樣做的好處就是內存中永遠只需要保留一行的數據,缺點就是每次訪問都要開啟Connect的連接。

           

          DataAdapter對象

          DataAdapter對象是ADO.NET數據訪問的核心。實際上它是數據集與數據庫的中間層。DataAdapter可以使用Fill方法來為DataTable或者DataSet填充數據。然后當內存操作完成后DataAdapter可以確認之前的操作從而對真正存于數據庫上的數據進行修改。

          DataAdapter包含四種屬性用來代表不同的數據庫命令:

          SelectCommand用來查詢數據

          InsertCommand用來插入數據

          DeleteCommand用來刪除數據

          UpdateCommand用來更新數據Update方法被調用后,數據集中的數據被更改然后拷貝回數據庫,緊接著使用InsertCommand, DeleteCommand, UpdateCommand中合適一個來進行數據更新。

          posted @ 2007-07-25 16:46 Picasso 閱讀(274) | 評論 (0)編輯 收藏

          DOM簡介

                   <name>Winter Blanket (78 inch)</name>
                   <price>20</price>
                   <qty>10</qty>
                </item>
             </order>
          </orders>
              在 DOM 中,使用 XML 信息意味著首先將它劃分為節點。

          posted @ 2007-07-25 16:34 Picasso 閱讀(261) | 評論 (0)編輯 收藏

          COM與.NET的交互

           
           Advanced COM Interop


          .NET framework 是從COM的一種自然地進步,因為這兩個模型共享了許多中心的主題,包括組件重用和語言中立。為了支持向后兼容,COM interop提供了不需要修改現有組件而能訪問現有COM組件的方法。可以通過使用COM interop工具導入相關的COM類型來合并COM組件到.NET Framework的應用中。一旦導入,COM的類型就可以使用了。

          COM interop 同時也提供了向前兼容使得COM的客戶可以像訪問其他的COM對象一樣訪問托管的代碼,COM interop又一次的提供了所謂的無縫從程序集中導出元數據(metadata)到類型庫并且像傳統COM組件一樣注冊托管組件的方法。無論是導出還是導入工具處理的結果都與COM規范一致。在運行時,如果需要的話common language runtime在COM對象和托管代碼之間列集(marshals)數據


          1. COM Wrappers
          COM在以下幾個方面與.NET Framework的對象模型有所不同:
          • COM對象的客戶程序必須管理這些對象的生命期;在.NET Framework 中CLR管理這些對象的生命期
          • COM的客戶通過請求一個接口并得到接口的指針來查詢一個服務是否有效,.NET的客戶可以通過反射(reflection)來得到一個對象的功能的描述
          • .NET的對象駐留在.NET Framework執行環境管理的內存中,執行環境可以因為性能的原因刪除內存中的對象并且更新它刪除的對象的所有引用。非托管的客戶,得到一個對象的指針,依賴于對象保留在相同的位置。這種客戶沒有那種處理在內存中不在固定位置的對象的機制。


          為了克服這些不同,runtime提供了包裝類使得托管代碼和非托管代碼的客戶都認為他們在自己的環境中調用對象的方法。當托管客戶調用一個COM對象的方法時,runtime創建一個runtime callable wrapper (RCW)。RCWs抽象了托管代碼和非托管代碼引用機制的不同。Runtime還創建了一個COM callable wrapper (CCW)來實現其逆過程,使得COM的客戶能夠無縫的調用.NET對象的方法。如下圖所示


          COM wrapper overview



          在大多數情況下,標準的RCW或者CCW由runtime生成,為跨越COM和.NET Framework的邊界調用提供了足夠的列集。使用自定義的屬性,可以隨意的調整runtime表示托管代碼和非托管代碼的方式

          Runtime Callable Wrapper


          CLR(common language runtime)通過一個叫做runtime callable wrapper (RCW)的代理(proxy)暴露COM 對象. 雖然RCW對于.NET的客戶似乎是一個普通的.NET對象,但是它的主要功能卻是在.NET客戶和COM對象之間列集調用。


          運行時正確的為每個COM對象創建一個RCW,而不管那個對象上存在的引用的個數。如下圖所示:任意數量的托管客戶可以保持一個暴露INew 和INewer 接口的COM對象的引用。運行時為每個COM對象維護一個單獨的RCW。


          Accessing COM objects through the runtime callable wrapper



          使用來源于類型庫(type library)的元數據(metadata),運行庫(runtime)創建將被調用COM對象和這個對象的包裝(wrapper)。每個RCW維護它所包裝的COM對象的接口指針并且在RCW不再需要時釋放COM對象。運行庫(runtime)在RCW之上作垃圾收集。


          在其他的活動中,RCW代表所包裝的對象在托管和非托管代碼之間列集(marshals)數據。特別的是,RCW在客戶和服務有不同的數據表現形式,并需要在他們之間傳遞數據時,提供方法參數和方法返回值得列集。


          標準的wrapper執行內置(built-in)的列集規則。例如:當.NET的客戶傳遞一個String類型作為參數的一部分給托管對象的時候,wrapper把string類型那個轉化為BSTR類型。當COM對象返回一個BSTR給托管的調用著的時候,調用著收到一個string。無論是客戶還是服務端接受和發送數據都使用自己熟悉的類型。還有一些其他的類型不需要變化,例如:一個標準的wrapper將在托管和非托管代碼之間一直傳遞4-byte integer而不做任何變化。


          RCW的主要目標就是隱藏托管代碼模型和非托管代碼模型之間的差別,實現無縫的傳輸。RCW使用選擇的接口而不把它們暴露給.NET的客戶端,如下圖所示


          COM interfaces and the runtime callable wrapper



          當創建一個早期的COM對象的時候,RCW是一個特殊的類型。它實現了COM對象實現的一些接口并且暴露它們的方法,屬性和時間。如圖所示:RCW暴露了INew接口,但是使用了IUnknown 和IDispatch接口。RCW向.NET客戶暴露了INew的所有成員


          COM Callable Wrapper


          當COM的客戶調用.NET的對象時,CLR創建這個托管的對象和這個托管的對象COM callable wrapper(CCW),COM客戶可以使用CCW作為托管對象的一個代理,而不能夠直接使用.NET的對象。

           
          Runtime正確的創建托管對象的CCW,不管要求這個服務的COM客戶的數量。如下圖所示,多個COM客戶可以保持包含INew 接口的CCW的引用,CCW,反過來包含一個實現了接口和垃圾收集的托管對象的單獨的引用。COM和.NET的客戶可以同時在相同的托管對象是發起調用。


          Accessing .NET objects through COM callable wrapper


          COM callable wrappers對于運行在.NET Framework上的其他類是不可見的。它們的主要目的是在托管和非托管代碼之間列集(marshal)調用,而且CCWs同時也管理著它所包含對象的identity和對象的生存期(lifetime)


          Object Identity
          運行時(runtime)在它的能夠垃圾回收的堆里(garbage-collected heap)為.NET對象分配內存,這能使runtime需要的時候在內存中移動對象。相反,runtime在不能進行垃圾收集的堆上為CCW分配內存,使COM客戶能夠直接引用它。


          Object Lifetime
          與它所包含的.NET 對象不同,CCW是一個基于引用計數的傳統的COM。當CCW的引用計數減少到0,wrapper釋放自己在托管對象上的引用。沒有引用的托管的對象在下一次垃圾收集的周期內將被收集。


          Customizing Standard Wrappers
          這部分將描述如何自定義標準的runtime callable wrappers(RCW) and COM callable wrappers.(CCW)


          ? Runtime Callable Wrappers
          當.NET激活一個COM對象時,運行時(runtime)生成一個包含COM類型的runtime callable wrapper (RCW),如下圖所示, 運行時(runtime)使用從導入的類型庫而得到的元數據(metadata)來生成RCW。Wrapper根據interop marshaling service定義的規則列集數據。


          RCW generation and method calls




          有兩個方式可以自定義RCW。如果你可以修改Interface Definition Language (IDL)的源文件,你可以給type library file (TLB) 添加屬性然后導入TLB。還可以應用interop-specific attributes來導入類型生成新的程序集(assembly)支持自定義的標準RCWs被這些attributes限制


          To modify the IDL source

          1. Apply TLB attributes to libraries, types, members, and parameters. Use the custom keyword and an attribute value to change metadata. By applying TLB attributes, you can:
          • Specify the managed name of an imported COM type, instead of allowing the import utility to select the name according to standard conversion rules.
          • Explicitly define a destination namespace for the types in a COM library.
          2. Compile the IDL source code.
          3. Generate an assembly from the resulting type library file or from a dynamic link library file (DLL) that contains the type you intend to implement.


          To modify an imported assembly
          1. Import the type library file. Use the Type Library Importer (Tlbimp.exe) to generate an assembly DLL.
          2. Create a text file from the imported assembly by using the MSIL Disassembler (Ildasm.exe).
          3. Apply interop attributes to the text file.
          4. Generate a new assembly from the modified text file by using the MSIL Assembler (Ilasm.exe).


          ? COM Callable Wrappers
          COM callable wrapper (CCW) 向COM導出NET Framework對象. 通過把一個托管的工程編譯成一個DLL的程序集, 可以自動的創建需要的元數據來描述程序集中的類型. 當一個COM的客戶激活托管對象時,運行時使用元數據來生成CCW.
          自定義CCW,你的托管的代碼要遵循交互規范屬性(interop-specific attributes),并且把編譯代碼編譯成程序集,如下圖所示,在這個例子中,Tlbexp.exe把托管類型編譯為COM


          CCW 的生成和方法調用



          通過在代碼中添加屬性,可以在交互列集服務限定的范圍內改變接口和數據的列集行為。例如,可以你可以控制方法參數傳遞的格式,也可以控制程序集中的什么類型暴露給COM


          2 .托管和非托管的線程(Managed and Unmanaged Threading)


          COM組件使用套間(apartments)來同步資源的訪問。與之對應的是,托管對象使用同步區域(synchronized regions),同步原語例如互斥量(mutexes)鎖定和完成異步端口,同步上下文來保證所有的共享資源以線程安全的方式被使用。


          對于可交互性來說,CLR(common language runtime)在調用COM對象時,創建并初始化一個套間,一個托管的線程可以創建并且進入一個包含一個線程的single-threaded apartment (STA)或者包含多個線程的multi-threaded apartment (MTA)。當COM的套間和線程的套間兼容的時候,COM允許調用的線程直接調用COM對象的方法,如果套間不兼容,COM創建兼容的套間并通過代理列集(marshals)所有的調用。

           
          在第一個對非托管代碼的調用時,運行時調用CoInitializeEx來初始化MTA或者STA的COM套間。可以使用System.Threading.ApartmentState屬性來控制創建的套間的類型是MTA, STA, 或者Unknown.在代理存根或者TLB已經注冊后,不一定義定設定要設定這個屬性。
          下表列出了ApartmentState的枚舉值和對應的COM套間初始化調用

          ApartmentState enumeration value
          COM apartment initialization
          MTA
          CoInitializeEx(NULL, COINIT_MULTITHREADED)
          STA
          CoIntializeEx(NULL, COINIT_APARTMENTTHREADED)
          Unknown
          CoInitializeEx(NULL, COINIT_MULTITHREADED)

          COM對象和托管線程在不兼容的套間時,所有的調用都通過COM創建的代理,下面的代碼例子顯示了怎么在托管代碼重創建一個STA套間模型的COM對象AptSimple


          [C#]
          using System.Threading;
          using APTOBJLib;
          ...
          AptSimple obj = new AptSimple ();
          obj.Counter = 1;
          為了消除代理存根,顯著的提高性能,注意創建對象之前的ApartmentState
          [C#]
          using System.Threading;
          using APTOBJLib;
          ...
          Thread.CurrentThread.ApartmentState = ApartmentState.STA;
          AptSimple obj = new AptSimple ();
          obj.Counter = 1;
          設定套間狀態之后,可以向下面那樣通過程序查詢狀態
          [C#]
          Thread.CurrentThread.ApartmentState = ApartmentState.STA;
          if (Thread.CurrentThread.ApartmentState == ApartmentState.STA) {
          // All is OK.
          }
          else {
          // Incompatible apartment state.
          }

          3 托管和非托管的事件(Managed and Unmanaged Events)

          .NET Framework的事件模型與傳統的COM的事件模型不同。托管的事件模型基于委托(delegate),er非托管的事件(在COM中)基于連接點(connection points)。兩個模型都是緊耦合的事件系統,因為客戶(事件接受者)和服務(事件發送者)必須同時的運行。

          這一部分描述了怎樣過渡托管和非托管的事件系統,使得對象可以跨域交互邊界發送和接收事件。

          COM 事件
          這部分提供關于連接點的概要介紹以及用來說明COM事件相關的通用術語
          連接點在客戶和COM的服務器之間確立了一種雙向de通信機制。通過這種機制,COM服務器在事件發生時可以回調客戶。例如,服務器(像Microsoft Internet Explorer)可以發出一個事件來向客戶程序報告一個變化(例如標題變化)。客戶創建了一個叫做event sink內部的COM對象來響應通知,當收到通知,客戶可以執行事件相關的操作。


          event sink提供了向服務器暴露事件相關方法的接口。服務器通過這些事件相關的方法激發事件。客戶像實現普通的COM接口一樣實現event sink接口。服務器聲明這個接口為出接口,COM服務的作者在類型庫中隊這個接口應用source 屬性。服務器使用event sink接口的定義來確定sink并且invoke方法


          實現了event sink接口的COM客戶通常叫做event sink,或者簡單的稱為sink。
          在下圖中,sink實現了ISinkEvents接口,服務器可以激發事件
          連接點事件模型(Connection point event model)



          event sink的接口確定之后,sink必須與源對象建立連接,連接點的機制使用下面的過程連接sink和source:
          1. The sink queries a server object for the IConnectionPointContainer interface. If the object supports connection points, it returns a pointer.
          2. Using methods on the container object, the sink locates the IConnectionPoint interface representing a specific connection point. Since a server can support multiple outgoing interfaces, a client must match its sink to the interface identifier (IID) of a particular connection point interface.
          3. Having obtained the correct connection point object, the sink calls IConnectionPoint::Advise to register its sink interface pointer. The server (source) holds the connection (and raises events to it) until the client breaks the connection by calling IConnectionPoint::Unadvise.


          處理COM源發出的事件(Handling Events Raised by a COM Source)
          如果你不熟悉.NET Framework提供的基于委托(delegate-based)的事件模型,參考Handling and Raising Events。

          An imported delegate signature comprises the sink event interface, an underscore, the event name, and the word EventHandler: SinkEventInterface_EventNameEventHandler.
          .NET的客戶(event sink)可以接受現存的COM服務器(event source)的事件。COM interop在你的托管客戶的元數據中產生必要的委托。一個導入的委托簽名(signature)由sink event接口,一個下劃線,事件名稱和EventHandler組成


          與現存的COM事件源交互(To interoperate with an existing COM event source)
          1. Obtain the primary interop assembly for the COM server if the COM types are to be shared by other applications. A primary interop assembly contains metadata representing the converted type library and is signed by the publisher.
          Note If the primary interop assembly is not available or if the assembly is to be used privately, you can import the type library by using Tlbimp.exe or an equivalent API.
          The conversion process generates a delegate for each event; however, you only have to sink the events that interest you.
          2. You can use a metadata browser, such as Ildasm.exe, to identify events delegates.
          3. Consume events from the COM event source the same way you consume events from a managed event source.
          下面的例子說明了怎樣打開一個Internet Explorer窗口,得到Internet Explorer對象發出的事件并在托管的代碼中處理。Internet Explorer的類型(包括事件委托)的定義從被SHDocVw.dll導入為元數據,例子激發TitleChange事件
           

          [C#]
          namespace InternetExplorer
          {
              using System;
              using System.Runtime.InteropServices;
              using SHDocVw;
           
              public class Explorer
              {
                  public static void Main()
                  {
                      Explorer explorer = new Explorer();
                      explorer.Run();
                  }
                  public void Run()
                  {
                      Object o = null;
                      String s;
           
                      try
                      {
                          // Starts the browser.
                          m_IExplorer = new SHDocVw.InternetExplorer();
                      }
                      catch(Exception e)
                      {
                          Console.WriteLine("Exception when creating Internet
                          Explorer object {0}", e);
                          return;
                      }
           
                      // Wires your event handlers to m_IExplorer.
                      SetAllEvents();
           
                      try
                      { 
                          // Goes to the home page.
                          m_WebBrowser = (IWebBrowserApp) m_IExplorer;
                          m_WebBrowser.Visible = true;
                          m_WebBrowser.GoHome();
           
                          // Starts navigating to different URLs.
                          Console.Write("Enter URL (or enter to quit): ");
                          s = Console.ReadLine();
                          while (s != "" && m_IExplorer != null &&
                              m_WebBrowser != null)
                          {
                              m_WebBrowser.Navigate(s, ref o, ref o, ref o,
                                    ref o);
                              Console.Write("Enter URL (or enter to quit): ");     
                              s = Console.ReadLine();
                          }
           
                          m_WebBrowser.Quit();
                      }
                      catch(Exception sE)
                      {
                          if (m_IExplorer == null && m_WebBrowser == null)
                          {
                              Console.WriteLine("Internet Explorer has gone away");
                          }
                          else
                          {
                              Console.WriteLine("Exception happens {0}", sE);
                          }
                      }
                  }
                  // Uses the += syntax for adding delegates to events.
                  void SetAllEvents()
                  {
                      if (m_IExplorer != null)
                      {
                          // Title Change event
                          // DWebBrowserEvents2 is the name of the sink event
                          //interface.
                          // TitleChange is the name of the event.
                          // DWebBrowserEvents2_TitleChangeEventHandler is the
                          // delegate name assigned by TlbImp.exe.
                          DWebBrowserEvents2_TitleChangeEventHandler
               DTitleChangeE = new DWebBrowserEvents2_TitleChangeEventHandler(OnTitleChange);
                        m_IExplorer.TitleChange += DTitleChangeE;
                      }
                  }
          ///////////////////////////////////////////////////////////////////////
                  // Define event handlers.
                  // Document title changed
                  static void OnTitleChange(String Text)
                  {
                      Console.WriteLine("Title changes to {0}", Text);
                  }
            
          //////////////////////////////////////////////////////////////////////////
                  // The following are class fields.
                  static private SHDocVw.InternetExplorer m_IExplorer = null;
                  static private IWebBrowserApp m_WebBrowser = null;
              }
          }

          posted @ 2007-07-25 11:19 Picasso 閱讀(2458) | 評論 (0)編輯 收藏

          僅列出標題
          共4頁: 上一頁 1 2 3 4 
          主站蜘蛛池模板: 平阴县| 中方县| 桐柏县| 克东县| 紫云| 岳西县| 会理县| 防城港市| 锦屏县| 石渠县| 大方县| 冷水江市| 绍兴市| 军事| 汾阳市| 邵阳市| 阿拉善左旗| 页游| 博爱县| 靖远县| 安岳县| 杭锦旗| 晴隆县| 石泉县| 临海市| 永胜县| 新巴尔虎左旗| 县级市| 灵台县| 库尔勒市| 辽阳县| 淳安县| 临沂市| 正阳县| 莱州市| 朔州市| 加查县| 茂名市| 湖州市| 科技| 阿瓦提县|