WCF RIA Services 简化开发RIA n-tier 解决方案。让你快速构建Silverlight n-tier应用程序客户端与服务端的通信。下面我们来看一张图:
下面我们来构建一个简单的DEMO:
首先,下载Silverlight 4 Tools for Visual Studio 2010 ,建一个Silverlight project:
接下弹出对话框,记得Enable WCF RIA Services:
建立DEMO的表,并插入几条数据:
1: CREATE TABLE [dbo].[tblItem](
2: [ItemNumber] INT NOT NULL,
3: [ItemDescription] [varchar](50) NULL,
4: [Quantity] [int] NULL
5: CONSTRAINT [PK_tblItem] PRIMARY KEY CLUSTERED
6: (
7: [ItemNumber] ASC )
8: )
9:
10: INSERT INTO [tblItem]
11: ([ItemNumber]
12: ,[ItemDescription]
13: ,[Quantity])
14: VALUES ('1','Item Name1',1),
15: ('2','Item Name2',2),
16: ('3','Item Name3',3),
17: ('4','Item Name4',4),
18: ('5','Item Name5',5),
19: ('6','Item Name6',6)
接着我们对这个TABLE建EF4 DATA MODEL,这里我们将不再深入,待建立好后,创建DomainService:
然后选择那个Entities:
接下将会生成一个Service的文件:
1: namespace RIAServices.Web
2: {
3: using System;
4: using System.Collections.Generic;
5: using System.ComponentModel;
6: using System.ComponentModel.DataAnnotations;
7: using System.Data;
8: using System.Linq;
9: using System.ServiceModel.DomainServices.EntityFramework;
10: using System.ServiceModel.DomainServices.Hosting;
11: using System.ServiceModel.DomainServices.Server;
12:
13:
14: // Implements application logic using the BirdLLEntities context.
15: // TODO: Add your application logic to these methods or in additional methods.
16: // TODO: Wire up authentication (Windows/ASP.NET Forms) and uncomment the following to disable anonymous access
17: // Also consider adding roles to restrict access as appropriate.
18: // [RequiresAuthentication]
19: [EnableClientAccess()]
20: public class ItemService : LinqToEntitiesDomainService<BirdLLEntities>
21: {
22:
23: // TODO:
24: // Consider constraining the results of your query method. If you need additional input you can
25: // add parameters to this method or create additional query methods with different names.
26: // To support paging you will need to add ordering to the 'tblItems' query.
27: public IQueryable<tblItem> GetTblItems()
28: {
29: return this.ObjectContext.tblItems;
30: }
31:
32: public void InsertTblItem(tblItem tblItem)
33: {
34: if ((tblItem.EntityState != EntityState.Detached))
35: {
36: this.ObjectContext.ObjectStateManager.ChangeObjectState(tblItem, EntityState.Added);
37: }
38: else
39: {
40: this.ObjectContext.tblItems.AddObject(tblItem);
41: }
42: }
43:
44: public void UpdateTblItem(tblItem currenttblItem)
45: {
46: this.ObjectContext.tblItems.AttachAsModified(currenttblItem, this.ChangeSet.GetOriginal(currenttblItem));
47: }
48:
49: public void DeleteTblItem(tblItem tblItem)
50: {
51: if ((tblItem.EntityState == EntityState.Detached))
52: {
53: this.ObjectContext.tblItems.Attach(tblItem);
54: }
55: this.ObjectContext.tblItems.DeleteObject(tblItem);
56: }
57:
58: /// <summary>
59: /// Gets the TBL items by item number.
60: /// </summary>
61: /// <param name="itemnumber">The itemnumber.</param>
62: /// <returns></returns>
63: public IQueryable<tblItem> GetTblItemsByItemNumber(int itemnumber)
64: {
65: return this.ObjectContext.tblItems.Where(i => i.ItemNumber == itemnumber);
66: }
67: }
另一个是Metadata :
1: namespace RIAServices.Web
2: {
3: using System;
4: using System.Collections.Generic;
5: using System.ComponentModel;
6: using System.ComponentModel.DataAnnotations;
7: using System.Linq;
8: using System.ServiceModel.DomainServices.Hosting;
9: using System.ServiceModel.DomainServices.Server;
10:
11: // The MetadataTypeAttribute identifies tblItemMetadata as the class
12: // that carries additional metadata for the tblItem class.
13: [MetadataTypeAttribute(typeof(tblItem.tblItemMetadata))]
14: public partial class tblItem
15: {
16:
17: // This class allows you to attach custom attributes to properties
18: // of the tblItem class.
19: //
20: // For example, the following marks the Xyz property as a
21: // required property and specifies the format for valid values:
22: // [Required]
23: // [RegularExpression("[A-Z][A-Za-z0-9]*")]
24: // [StringLength(32)]
25: // public string Xyz { get; set; }
26: internal sealed class tblItemMetadata
27: {
28:
29: // Metadata classes are not meant to be instantiated.
30: private tblItemMetadata()
31: {
32: }
33:
34: public string ItemDescription { get; set; }
35:
36: public int ItemNumber { get; set; }
37:
38: public Nullable<int> Quantity { get; set; }
39: }
40: }
41: }
然后打开Data—>Show Data Source,如下图:
然后打开另一个Project中Mainpage.xaml,我们之前应用生成这样的XMAL:
1: <UserControl x:Class="RIAServices.MainPage"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: mc:Ignorable="d"
7: d:DesignHeight="536" d:DesignWidth="463" xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:RIAServices.Web" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
8:
9: <Grid x:Name="LayoutRoot" Background="White" Height="536" Width="463">
10: <Grid.ColumnDefinitions>
11: <ColumnDefinition Width="140*" />
12: <ColumnDefinition Width="47*" />
13: <ColumnDefinition Width="405*" />
14: </Grid.ColumnDefinitions>
15: <riaControls:DomainDataSource AutoLoad="False" d:DesignData="{d:DesignInstance my:tblItem, CreateList=true}" Height="0" LoadedData="tblItemDomainDataSource_LoadedData" Name="tblItemDomainDataSource" QueryName="GetTblItemsQuery" Width="0" Margin="0,0,140,393">
16: <riaControls:DomainDataSource.DomainContext>
17: <my:ItemContext />
18: </riaControls:DomainDataSource.DomainContext>
19: </riaControls:DomainDataSource>
20: <sdk:DataGrid AutoGenerateColumns="False" Height="181" HorizontalAlignment="Left" ItemsSource="{Binding ElementName=tblItemDomainDataSource, Path=Data}" Name="tblItemDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="400" Margin="0,58,0,0" Grid.ColumnSpan="3">
21: <sdk:DataGrid.Columns>
22: <sdk:DataGridTextColumn x:Name="itemDescriptionColumn" Binding="{Binding Path=ItemDescription}" Header="Item Description" Width="SizeToHeader" />
23: <sdk:DataGridTextColumn x:Name="itemNumberColumn" Binding="{Binding Path=ItemNumber, Mode=OneWay}" Header="Item Number" IsReadOnly="True" Width="SizeToHeader" />
24: <sdk:DataGridTextColumn x:Name="quantityColumn" Binding="{Binding Path=Quantity}" Header="Quantity" Width="SizeToHeader" />
25: </sdk:DataGrid.Columns>
26: </sdk:DataGrid>
27: <Button Content="Query" Height="23" HorizontalAlignment="Left" Margin="171,12,0,0" Name="btnquery" VerticalAlignment="Top" Width="75" Click="btnquery_Click" Grid.Column="2" />
28: <TextBox Height="23" HorizontalAlignment="Left" Margin="1,12,0,0" Name="txtItemNumber" VerticalAlignment="Top" Width="120" Grid.ColumnSpan="2" />
29: <sdk:DataGrid AutoGenerateColumns="False" Height="179" HorizontalAlignment="Left" ItemsSource="{Binding ElementName=tblItemDomainDataSource, Path=Data}" Margin="1,320,0,0" Name="dataGrid1" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="400" Grid.ColumnSpan="3">
30: <sdk:DataGrid.Columns>
31: <sdk:DataGridTextColumn x:Name="dataGridTextColumn1" Binding="{Binding Path=ItemDescription}" Header="Item Description" Width="SizeToHeader" />
32: <sdk:DataGridTextColumn x:Name="dataGridTextColumn2" Binding="{Binding Path=ItemNumber, Mode=OneWay}" Header="Item Number" IsReadOnly="True" Width="SizeToHeader" />
33: <sdk:DataGridTextColumn x:Name="dataGridTextColumn3" Binding="{Binding Path=Quantity}" Header="Quantity" Width="SizeToHeader" />
34: </sdk:DataGrid.Columns>
35: </sdk:DataGrid>
36: <sdk:Label Grid.ColumnSpan="3" Height="21" HorizontalAlignment="Left" Margin="1,281,0,0" Name="label1" VerticalAlignment="Top" Width="189" Content="CustomerService from ADO.NET" />
37: </Grid>
38: </UserControl>
为了对比我们建立另一个自定义DomainService, 也需要建立一个Entity:
1: using System;
2: using System.Collections.Generic;
3: using System.ComponentModel;
4: using System.ComponentModel.DataAnnotations;
5: using System.Linq;
6: using System.ServiceModel.DomainServices.Hosting;
7: using System.ServiceModel.DomainServices.Server;
8:
9: namespace RIAServices.Web
10: {
11: public class Item
12: {
13: [Key]
14: public int ItemNumber { get; set; }
15: public string ItemDescription { get; set; }
16: public Nullable<int> Quantity { get; set; }
17: }
18: }
CustomerDomainService,里面我们使用原生态的ADO.NET进行数据访问,你也可以替代成你自己的数据Provider.
1: [EnableClientAccess()]
2: public class CustomerDomainService : DomainService
3: {
4: public List<Item> GetItemsFromDatabase()
5: {
6: SqlConnection sqlConnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MainDb"].ToString());
7: DataSet objSet = new DataSet();
8: SqlCommand sqlCommand = new SqlCommand();
9: sqlCommand.Connection = sqlConnection;
10: sqlCommand.CommandText = "Select * FROM tblItem";
11: SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
12: sqlDataAdapter.SelectCommand = sqlCommand;
13: sqlDataAdapter.Fill(objSet);
14:
15: List<Item> lstResult = new List<Item>();
16: Item objEmployee;
17:
18: if (objSet.Tables.Count > 0)
19: {
20: foreach (DataRow dr in objSet.Tables[0].Rows)
21: {
22: objEmployee = new Item();
23: objEmployee.Quantity = Convert.ToInt32(dr["Quantity"]);
24: objEmployee.ItemDescription = dr["ItemDescription"].ToString();
25: objEmployee.ItemNumber = Convert.ToInt32(dr["ItemNumber"]);
26: lstResult.Add(objEmployee);
27: }
28: }
29: return lstResult;
30: }
31: }
最后我们来看MainPage.xaml.cs 的代码:
1: public partial class MainPage : UserControl
2: {
3: public MainPage()
4: {
5: InitializeComponent();
6:
7: var itemContext = new ItemContext();
8: tblItemDataGrid.ItemsSource = itemContext.tblItems;
9: EntityQuery<tblItem> s = itemContext.GetTblItemsQuery();
10: LoadOperation<tblItem> op = itemContext.Load(s);
11:
12: //Use another domain service
13: var customerservice = new CustomerDomainContext();
14: dataGrid1.ItemsSource = customerservice.Items;
15: EntityQuery<Item> s2 = customerservice.GetItemsFromDatabaseQuery();
16: LoadOperation<Item> op2 = customerservice.Load(s2);
17:
18: }
19:
20: private void tblItemDomainDataSource_LoadedData(object sender, System.Windows.Controls.LoadedDataEventArgs e)
21: {
22: if (e.HasError)
23: {
24: System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
25: e.MarkErrorAsHandled();
26: }
27: }
28:
29: /// <summary>
30: /// Handles the Click event of the btnquery control.
31: /// </summary>
32: /// <param name="sender">The source of the event.</param>
33: /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
34: private void btnquery_Click(object sender, RoutedEventArgs e)
35: {
36: var tt = new ItemContext();
37: tblItemDataGrid.ItemsSource = tt.tblItems;
38: EntityQuery<tblItem> s = tt.GetTblItemsByItemNumberQuery(txtItemNumber.Text == "" ? 0 : Convert.ToInt32(txtItemNumber.Text));
39: LoadOperation<tblItem> op = tt.Load(s);
40: }
41:
42: }
这里我们禁用了默认SilverLight DataGrid的自动绑定,在InitializeComponent方法后增加了代码绑定。btnquery_Click方法对应的是UI上那个Button的Click事件,用来做数据查询。
另一个要注意是ItemService中的GetTblItemsByItemNumber方法是后面加入的,其它方法是自动生成的。最后F5运动后效果是:
简单查询的结果:
这个后面访问了WCF Service地址是:
http://localhost:54934/Services/RIAServices-Web-ItemService.svc
通过Monitor我们看到GetItemsFromDatabase方法返回的数据是:
@GetItemsFromDatabaseResponsehttp://tempuri.org/@GetItemsFromDatabaseResult aDomainServices i)http://www.w3.org/2001/XMLSchema-instance^
TotalCount?^ RootResults b7http://schemas.datacontract.org/2004/07/RIAServices.Web_Item_ItemDescription?Item Name1_
ItemNumber僟Quantity?_Item_ItemDescription?Item Name2_
ItemNumber?_Quantity?_Item_ItemDescription?Item Name3_
ItemNumber?_Quantity?_Item_ItemDescription?Item Name4_
ItemNumber?_Quantity?_Item_ItemDescription?Item Name5_
ItemNumber?_Quantity?_Item_ItemDescription?Item Name6_
ItemNumber?_Quantity?
这是WCF RIA Service默认的数据格式。有时间将在以后解析它们。希望对您的开发有帮助。
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。