WCF RIA Services 简化开发RIA n-tier 解决方案。让你快速构建Silverlight n-tier应用程序客户端与服务端的通信。下面我们来看一张图:

IC357993

下面我们来构建一个简单的DEMO:

首先,下载Silverlight 4 Tools for Visual Studio 2010 ,建一个Silverlight project:

Create Silverlight Project in VS2010

接下弹出对话框,记得Enable WCF RIA Services:

VS2010 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:

Create Domain Serivce

然后选择那个Entities:

Domain Service - New Domain Service Class

接下将会生成一个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,如下图:

Domain Context

然后打开另一个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运动后效果是:

image

简单查询的结果:

image

这个后面访问了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

posted on 2010-10-21 18:21  PetterLiu  阅读(2957)  评论(3编辑  收藏  举报