Silverlight 2.0 資料庫應用程式開發 (1) 文 / 黃忠成 從 Silverlight 1.0 到 Silverlight 2.0 我想不用我贅言,相較於 Silverlight 1.0 的陽春, Silverlight 2.0 提供了更完整的資料庫支援,其最主要的部份在於提供了 WCF/http 的網路機制及客戶端的控件 Binding 技術,有了這兩個機制,我們可以透過 WCF/http 網路機制連回 Server 端取得資料,然後以 Binding 技術將控件與資料結合在一起,設計出類似 windows Form/WPF UI 介面的強大網頁資料庫應用程式。 Silverlight 2.0 與 N-TIEr 對於部份的 ASP.NET 設計師而言,對 Silverlight 2.0 的資料庫應用程式的開發模式會有些陌生,在 ASP.NET 設計模式中,我們可以直接使用 ADO.NET 來取得資料,接著利用 GrIDVIEw 等資料控件將資料顯現於網頁上,此時的系統架構如圖 SL001 。 圖 SL001 但在 Silverlight 2.0 中,並未提供 ADO.NET 這個機制,從網頁應用程式角度上看, Silverlight 2.0 是一種 ClIEnt Application 架構,運行於 IE 等瀏覽器平台之上,因此若要提供 ADO.NET 機制,那麼後端的資料庫必定得曝露於網際網路之上,而你肯定無法接受將 sql Server 曝露在網路上供人存取,因為這會帶來安全性、授權費等問題。所以,當使用 Silverlight 2.0 時,我們必須找一個相對於 ADO.NET 的機制來做為取得資料的中介層,這種設計模式就稱為 N-TIEr ,見圖 SL002 。 圖 SL002 如圖 SL002 所示, Silverlight 應用程式是內嵌於 HTML 中下載,她可以透過 WCF/httpWebRequest 網路機制連回來源的 Web Site 取得資料,問題在於後端的 Web Site 如何接收來自 Silverlight 的網路要求?在 Silverlight 2.0 中,你有兩種選擇,一是在 Web Site 端建立一個簡單的網頁,收取來自 Silverlight 的網路要求,接著輸出 XML 或是 JsON 格式的資料。二是透過 .NET 的 WCF 機制,於 Web Site 端建立一個 WCF Service ,於 Silverlight 中透過此 WCF Service 來取得資料。兩種機制各有其優缺點,方法一可以適用於所有網頁平台,例如 ASP 、 PHP 、 JsP 皆可,而方法二則是僅限於支援 Web Service 的網頁平台。 在開始設計實際應用程式之時,你必須先了解所謂 N-TIEr 架構的定義,所謂的 N-TIEr 指的是將整個程式架構切分為三個層面,第一層是展現層,也就是你的 Silverlight 應用程式,用來顯示資料及接受使用者 *** 作,第二層指的服務層,用來提供資料及回應來自展示層的要求,第三層則是資料層,用來由資料庫取得資料或是更新資料。 N-TIEr 早期的發展是為了分擔資料庫系統的繁重工作,以 [ 偶而連線 ] 、 [ 負載平衡 ] 等技巧,減輕本來必須全部交與資料庫處理的工作。舉個例來說,一系統擁有 10000 個使用者,當使用傳統的 ClIEnt/Server 架構時,這 10000 個使用者會握有 10000 個資料連線,當這些使用者發出要求資料的 SELECT 需求時,資料庫系統就得負擔產生 10000 個資料集的工作,但這 10000 個需求中,很有可能有一半以上是要求同一份資料。當使用 N-TIEr 架構時,我們就可以在服務層中快取已取過的資料,當有同樣要求來臨時,直接以回傳快取資料的方式取代由資料庫系統取得的動作,這樣自然就減輕了資料庫的負擔,提高系統所能承載的用戶數量。 在早期網際網路頻寬不足的環境下, N-TIEr 架構原始設計中每個動作都要透過連結服務層的模式顯得有些不切實際,因為使用者可能處於一個低頻寬的環境、甚至是無網路可用的窘境,在這種模式下,存取服務層是種奢侈。因此, N-TIEr 發展出一種名為 [ 偶爾連線 ] 的模式,展示層在有網路的情況下,將資料由服務層取回後快取於客戶端,此時使用者可以自由的 *** 作展示層來新增、修改、刪除及查詢資料,這些動作全以客戶端的快取為主,待有網路時,再將異動資料整批傳回服務層更新回資料庫。 [ 偶爾連線 ] 的架構很完美,也很符合當年的需求,但隨著網路的普遍化及高覆蓋率,設計 [ 偶而連線 ] 架構所需付出的代價就顯得有些累贅了, [ 偶爾連線 ] 的架構建立在完善的客戶端快取機制及客戶端查詢機制下,而這些機制並不容易建構。所以,現在的 N-TIEr 轉變為以 [ 連線模式 ] 為主。 Silverlight 2.0 的架構趨近於 [ 連線模式 ] ,這意味著 Silverlight 2.0 的應用程式將運行在一個可存取網站的環境下,當這個網站存在於本機時,程式不需要網路便可執行,當網站不存在於本機時,則需要網路方能運行。
註:多數瀏覽器都有一種以離線模式執行網頁的設定,將離線模式打開,你依舊能在離線模式下運行 Silverlight 程式,在適當的設計下,其實也能做出 [ 偶爾連線 ] 模式。 |
DBProvIDer.ashx.cs |
using System; using System.Collections.Generic; using System.linq; using System.Web; using System.Data; using System.Data.sqlClIEnt; using System.Configuration; using System.Xml.linq; namespace DBDemo1.Web { ///<summary> /// Summary description for $codebehindclassname$ ///</summary> public class DBProvIDer : IhttpHandler { public voID ProcessRequest(httpContext context) { context.Response.ContentType = "text/xml"; using (sqlConnection conn = new sqlConnection(@"Data Source=./sqlEXPRESS;AttachDbfilename=|DataDirectory|/MyDatabase.mdf;Integrated Security=True;User Instance=True")) { Xdocument doc = new Xdocument(new XElement("Root")); using (sqlCommand cmd = new sqlCommand("SELECT * FROM CUSTOMERS",conn)) { conn.open(); using (sqlDataReader reader = cmd.ExecuteReader( CommandBehavior.CloseConnection)) { while (reader.Read()) { XElement elem = new XElement("Customer"); elem.Add(new XAttribute("CUSTOMER_ID", reader.GetString(reader.Getordinal("CUSTOMER_ID")))); elem.Add(new XAttribute("CUSTOMER_name", reader.GetString(reader.Getordinal("CUSTOMER_name")))); doc.Root.Add(elem); } } context.Response.Write(doc.ToString()); context.Response.Flush(); context.Response.End(); } } } public bool IsReusable { get { return false; } } } } |
Page.xaml |
< UserControl x : Class ="DBDemo1.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.windows.Controls;assembly=System.windows.Controls.Data" WIDth="400" Height="300" Loaded="UserControl_Loaded"> < GrID x : name ="LayoutRoot" Background ="White" Height ="300" WIDth ="400"> < data : DataGrID x : name ="grID" autoGenerateColumns ="True"> </ data : DataGrID > </ GrID > </ UserControl > |
Page.xaml.cs |
using System; using System.Collections.Generic; using System.linq; using System.Net; using System.windows; using System.windows.Controls; using System.windows.documents; using System.windows.input; using System.windows.Media; using System.windows.Media.Animation; using System.windows.Shapes; using System.IO; using System.Xml; using System.Xml.linq; namespace DBDemo1 { public partial class Page : UserControl { public Page() { InitializeComponent(); } private voID UserControl_Loaded(object sender,RoutedEventArgs e) { httpWebRequest request = (httpWebRequest)WebRequest.Create( new Uri("http://localhost:40419/DBProvIDer.ashx",UriKind.absolute)); request.Method = "POST"; request.BeginGetRequestStream(new AsyncCallback(ReadCallback),request); } private voID ReadCallback(IAsyncResult state) { httpWebRequest request = (httpWebRequest)state.AsyncState; Stream poststream = request.EndGetRequestStream(state); //byte[] buff = System.Text.EnCoding.Unicode.GetBytes("TEST"); //poststream.Write(buff,buff.Length); poststream.Close(); // the request stream must closed before request.BeginGetResponse(new AsyncCallback(GetResponse),request); } private voID GetResponse(IAsyncResult state) { httpWebRequest request = (httpWebRequest)state.AsyncState; httpWebResponse response = (httpWebResponse)request.EndGetResponse(state); using (Stream stream = response.GetResponseStream()) { Xdocument doc = Xdocument.Load(stream); dispatcher.BeginInvoke( new System.Threading.ParameterizedThreadStart(UpdateUI), doc); } } private voID UpdateUI(object state) { Xdocument doc = (Xdocument)state; grID.ItemsSource = (from s1 in doc.Elements("Root").Descendants("Customer") select new Customer() { ID = s1.Attribute("CUSTOMER_ID").Value, name = s1.Attribute("CUSTOMER_name").Value }).ToList(); } } public class Customer { public string ID { get; set; } public string name { get; set; } } } |
DBService.svc.cs |
using System; using System.Collections.Generic; using System.linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace DBDemo1.Web { [ServiceContract] public interface IDBService { [OperationContract] CUSTOMERS[] GetData(); } public class DBService : IDBService { public CUSTOMERS[] GetData() { using (MyDBDataContext context = new MyDBDataContext()) { return (from s1 in context.CUSTOMERS select s1).ToArray(); } } } } |
web.config |
............ < services > < service behaviorConfiguration = "DBDemo1.Web.DBServiceBehavior" name = "DBDemo1.Web.DBService"> < endpoint address = ""binding="basichttpBinding"contract="DBDemo1.Web.IDBService"> < IDentity > < dns value = "localhost" /> </ IDentity > </ endpoint > < endpoint address = "mex"binding="mexhttpBinding"contract="IMetadataExchange" /> </ service > </ services > ............ |
Page2.xaml |
< UserControl x : Class ="DBDemo1.Page2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.windows.Controls;assembly=System.windows.Controls.Data" WIDth="400" Height="300" Loaded="UserControl_Loaded"> < GrID x : name ="LayoutRoot" Background ="White" Height ="300" WIDth ="400"> < data : DataGrID x : name ="grID" autoGenerateColumns ="True"> </ data : DataGrID > </ GrID > </ UserControl > |
Page2.xaml.cs |
using System; using System.Collections.Generic; using System.linq; using System.Net; using System.windows; using System.windows.Controls; using System.windows.documents; using System.windows.input; using System.windows.Media; using System.windows.Media.Animation; using System.windows.Shapes; namespace DBDemo1 { public partial class Page2 : UserControl { public Page2() { InitializeComponent(); } private voID UserControl_Loaded(object sender,RoutedEventArgs e) { ServiceReference1.DBServiceClIEnt clIEnt = new DBDemo1.ServiceReference1.DBServiceClIEnt(); clIEnt.GetDataCompleted += new EventHandler<DBDemo1.ServiceReference1.GetDataCompletedEventArgs>( clIEnt_GetDataCompleted); clIEnt.GetDataAsync(); } voID clIEnt_GetDataCompleted(object sender, DBDemo1.ServiceReference1.GetDataCompletedEventArgs e) { grID.ItemsSource = e.Result; } } } |
WebDataService1.svc.cs |
using System; using System.Collections.Generic; using System.Data.Services; using System.linq; using System.ServiceModel.Web; using System.Web; namespace DBDemo1.Web { public class WebDataService1 : DataService< EntityData.MyDatabaseEntitIEs> { // This method is called only once to initialize service-wIDe policIEs. public static voID InitializeService(IDataServiceConfiguration config) { config.SetEntitySetAccessRule("*",EntitySetRights.All); config.SetServiceOperationAccessRule("*",ServiceOperationRights.All); } } } |
Page3.xaml |
< UserControl x : Class ="DBDemo1.Page3" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.windows.Controls;assembly=System.windows.Controls.Data" WIDth="400" Height="300" Loaded="UserControl_Loaded"> < GrID x : name ="LayoutRoot" Background ="White" Height ="300" WIDth ="400"> < data : DataGrID x : name ="grID" autoGenerateColumns ="True"> </ data : DataGrID > </ GrID > </ UserControl > |
Page3.xaml.cs |
using System; using System.Collections.Generic; using System.linq; using System.Net; using System.windows; using System.windows.Controls; using System.windows.documents; using System.windows.input; using System.windows.Media; using System.windows.Media.Animation; using System.windows.Shapes; using System.Data.Services.ClIEnt; namespace DBDemo1 { public partial class Page3 : UserControl { public Page3() { InitializeComponent(); } private voID UserControl_Loaded(object sender,RoutedEventArgs e) { ServiceReference2.MyDatabaseEntitIEs3 entitIEs = new DBDemo1.ServiceReference2.MyDatabaseEntitIEs3( new Uri("WebDataService1.svc",UriKind.relative)); var result = from s1 in entitIEs.CUSTOMERS select s1; ((DataServicequery<ServiceReference2.CUSTOMERS>)result).BeginExecute( new AsyncCallback(ReadCallback),result); } private voID ReadCallback(IAsyncResult state) { DataServicequery<ServiceReference2.CUSTOMERS> svcCtx = (DataServicequery<ServiceReference2.CUSTOMERS>)state.AsyncState; //remember,you must call toList,toarray before set to itemsource. grID.ItemsSource = svcCtx.EndExecute(state).ToList(); } } } |
Page4.xaml |
< UserControl x : Class ="DBDemo1.Page4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.windows.Controls;assembly=System.windows.Controls.Data" WIDth="400" Height="300" Loaded="UserControl_Loaded"> < GrID x : name ="LayoutRoot" Background ="White" Height ="300" WIDth ="400"> < data : DataGrID x : name ="grID" autoGenerateColumns ="True"> </ data : DataGrID > </ GrID > </ UserControl > |
Page4.xaml.cs |
using System; using System.Collections.Generic; using System.linq; using System.Net; using System.windows; using System.windows.Controls; using System.windows.documents; using System.windows.input; using System.windows.Media; using System.windows.Media.Animation; using System.windows.Shapes; using System.IO; using System.IO.IsolatedStorage; using System.Xml.linq; namespace DBDemo1 { public partial class Page4 : UserControl { public Page4() { InitializeComponent(); } private voID UserControl_Loaded(object sender,RoutedEventArgs e) { httpWebRequest request = (httpWebRequest)WebRequest.Create( new Uri("http://localhost:40419/DBProvIDer.ashx",request); } private voID ReadCallback(IAsyncResult state) { httpWebRequest request = (httpWebRequest)state.AsyncState; Stream poststream = request.EndGetRequestStream(state); //byte[] buff = System.Text.EnCoding.Unicode.GetBytes("TEST"); //poststream.Write(buff,request); } private voID GetResponse(IAsyncResult state) { try { httpWebRequest request = (httpWebRequest)state.AsyncState; httpWebResponse response = (httpWebResponse)request.EndGetResponse(state); using (Stream stream = response.GetResponseStream()) { using (var store = IsolatedStoragefile.GetUserStoreForApplication()) { store.CreateDirectory("Data"); IsolatedStoragefileStream subDirfile = store.Createfile(System.IO.Path.Combine("Data","dbdata.txt")); using (StreamWriter sw = new StreamWriter(subDirfile)) { using(StreamReader sr = new StreamReader(stream)) { sw.Write(sr.ReadToEnd()); } } } Xdocument doc = Xdocument.Load(stream); dispatcher.BeginInvoke( new System.Threading.ParameterizedThreadStart(UpdateUI),doc); } } catch (Exception ex) { using (var store = IsolatedStoragefile.GetUserStoreForApplication()) { IsolatedStoragefileStream subDirfile = store.Openfile(System.IO.Path.Combine("Data","dbdata.txt"),fileMode.Open); Xdocument doc = Xdocument.Load(subDirfile); subDirfile.Close(); dispatcher.BeginInvoke( new System.Threading.ParameterizedThreadStart(UpdateUI),doc); } } } private voID UpdateUI(object state) { Xdocument doc = (Xdocument)state; grID.ItemsSource = (from s1 in doc.Elements("Root").Descendants("Customer") select new Customer() { ID = s1.Attribute("CUSTOMER_ID").Value, name = s1.Attribute("CUSTOMER_name").Value }).ToList(); } } } |
以上是内存溢出为你收集整理的Silverlight 2.0 資料庫應用程式開發(1)全部内容,希望文章能够帮你解决Silverlight 2.0 資料庫應用程式開發(1)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)