Silverlight 2.0 資料庫應用程式開發(1)

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來取得資料。兩種機制各有其優缺點,方法一可以適用於所有網頁平台,例如ASPPHPJSP皆可,而方法二則是僅限於支援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程式,在適當的設計下,其實也能做出[偶爾連線]模式。
使用HttpWebRequest
在大略了解Silverlight 2.0N-Tier架構後,我們便可以開始撰寫Silverlight 2.0的資料庫應用程式,請建立一個Silverlight 2.0專案,接著於Web結尾之Project添加一資料庫。
SL003
SL004
然後添加一資料表至資料庫中。
SL005
建立結構。
SL006
添加資料列。
SL007
SL008
完成資料庫準備工作後,現在便可開始實作服務層,在這小節中,我們以傳統網頁模式來建立服務層,請於Web結尾之專案中添加一Generic Handler(你也可以使用.aspx)
SL009

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;
}
}
}
}
透過IE來測試此服務層是否運作正常。
SL010
由於本例將使用DataGrid控件,因此你必須透過Add Reference(加入參考)來添加DataGrid所需要的AssemblySilverlight專案(沒有Web結尾的那一個)
SL011
SL012
另外,由於服務層使用XML,我們可以利用Silverlight 2.0所提供的LINQ To XML來簡化解譯XML的工作,LINQ To XML需要添加System.XML.Linq.dll為參考,請透過Add Reference來添加System.XML.Linq.dllSilverlight專案中(沒有Web結尾的那一個)
SL013
接著在Page.xaml中鍵入以下的XAML

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中鍵入以下的程式碼。

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, 0, 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; }
}
}
SL014是此例執行結果。
SL014
透過HttpWebRequest的模式,我們可以用傳統網頁來扮演服務層,這可應用於多數網頁平台如PHPASPJSP之上。
使用WCF
使用HTTPWebRequest的方式雖然簡單,但缺點是我們得自訂其間資料傳送的格式,最大化相容性的結果也限縮了結構性,所幸在現今網路世界中早已定義了多數網頁平台都支援的資料格式,那就是SOAP/Web ServiceSilverlight 2.0除了允許我們撰寫Web Service的客戶端外,同時也支援了.NET Framework 3.0中所新增的WCF Service,本例就以WCF Service做為服務層,請添加一個Web ServiceWeb結尾的專案中。
SL015
然後添加一個LINQ To SQL ClassesWeb結尾的專案中,做為取代ADO.NET的資料存取機制。
SL016
添加資料表至.DBML中。
SL017
刪除自動產生的IDBService.cs,然後於DBService.svc.cs中鍵入以下程式碼。

DBService.svc.cs
using System;
using System.Collections.Generic;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值