zoukankan      html  css  js  c++  java
  • 稳扎稳打Silverlight(57) 4.0通信之WCF RIA Services: 概述, 通过 DomainDataSource 实现数据的添加、查询、更新和删除操作

    [索引页]
    [源码下载]


    稳扎稳打Silverlight(57) - 4.0通信之WCF RIA Services: 概述, 通过 DomainDataSource 实现数据的添加、查询、更新和删除操作



    作者:webabcd


    介绍
    Silverlight 4.0 之 WCF RIA Services:概述以及如何通过 DomainDataSource 实现数据的添加、查询、更新和删除操作,以及服务端的查询、排序和分页等逻辑


    在线DEMO
    http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html


    示例
    1、概述
    Summary.xaml

    代码
    <navigation:Page x:Class="Silverlight40.WCFRIAServices.Summary" 
               xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               Title
    ="Summary Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">
                
                
    <StackPanel Orientation="Horizontal">
                    
    <Image Source="/WCFRIAServices/1.png" Margin="10" />
                    
    <Image Source="/WCFRIAServices/2.png" Margin="10" />
                    
    <Image Source="/WCFRIAServices/3.png" Margin="10" />
                
    </StackPanel>
                
                
    <TextBlock>
                    
    <Run>1、WCF RIA Services link - 用于连接中间层和表现层,在 Silverlight 项目的属性中可以设置 WCF RIA Services link</Run>
                    
    <LineBreak />
                    
    <Run>2、图1:最简单的 WCF RIA Services link;图2:带有类库的 WCF RIA Services link;图3:带有多个 RIA Services 类库的 WCF RIA Services link</Run>
                    
    <LineBreak />
                    
    <Run>3、在服务端创建 Domain Service Class 用于提供服务,客户端的 Generated_Code 文件夹内会自动生成数据上下文代码</Run>
                    
    <LineBreak />
                    
    <Run>4、共享代码:中间层按 *.shared.cs 规范保存的代码会 push 到表现层的 Generated_Code 文件夹内;文件链接:添加已存在文件时,选择“Add As Link”,此为 pull 模型</Run>
                
    </TextBlock>
                
            
    </StackPanel>
        
    </Grid>
    </navigation:Page>



    2、演示 DomainDataSource 的应用
    服务端:
    MyDomainService.cs

    代码
    /*
     * 一个 Domain Service 服务
     
    */

    namespace Silverlight40.Web.Service
    {
        
    using System;
        
    using System.Collections.Generic;
        
    using System.ComponentModel;
        
    using System.ComponentModel.DataAnnotations;
        
    using System.Data;
        
    using System.Linq;
        
    using System.ServiceModel.DomainServices.EntityFramework;
        
    using System.ServiceModel.DomainServices.Hosting;
        
    using System.ServiceModel.DomainServices.Server;
        
    using Silverlight40.Web.Model;

        
    /*
         * 用 LinqToEntities 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>;用 LinqToSql 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>
         * Domain Service 内所有对客户端可见的方法都应该是 public 的,Domain Service 内的方法不支持重载
         * 对客户端可见的方法要满足命名约定,或为其指定对应的 Attribute。当前支持 6 种数据操作:Query, Update, Insert, Delete, Invoke, Named Update, 详见文档
         * 
         * [EnableClientAccess()] - 该类对客户端可见
         * [EnableClientAccess(RequiresSecureEndpoint = true)] - 使用 HTTPS 协议
         * [Ignore] - 指定的方法不作为服务而公开
         * [Query(IsComposable=true)] - 支持客户端的 linq 查询,而且此查询会被在服务端执行
         * 
         * 在多个 Domain Services 间共享实体:通过 [ExternalReference], [Association()], Context.AddReference() 实现,详见文档
         
    */

        
    // 服务端的类名为:MyDomainService,则其生成的客户端上下文的类名为:MyDomainContext
        [EnableClientAccess()]
        
    public class MyDomainService : LinqToEntitiesDomainService<NorthwindEntities>
        {
            [Query(IsDefault 
    = true)]
            
    public IQueryable<Category> GetCategories()
            {
                
    return this.ObjectContext.Categories;
            }

            
    public void InsertCategory(Category category)
            {
                
    if ((category.EntityState != EntityState.Detached))
                {
                    
    this.ObjectContext.ObjectStateManager.ChangeObjectState(category, EntityState.Added);
                }
                
    else
                {
                    
    this.ObjectContext.Categories.AddObject(category);
                }
            }

            
    public void UpdateCategory(Category currentCategory)
            {
                
    this.ObjectContext.Categories.AttachAsModified(currentCategory, this.ChangeSet.GetOriginal(currentCategory));
            }

            
    public void DeleteCategory(Category category)
            {
                
    if ((category.EntityState == EntityState.Detached))
                {
                    
    this.ObjectContext.Categories.Attach(category);
                }
                
    this.ObjectContext.Categories.DeleteObject(category);
            }



            [Query(IsDefault 
    = true)]
            
    public IQueryable<Product> GetProducts()
            {
                
    return this.ObjectContext.Products;
            }

            
    public IQueryable<Product> GetProductsBySort(string sort)
            {
                
    return ObjectContext.Products.OrderBy(sort);
            }

            
    public void InsertProduct(Product product)
            {
                
    if ((product.EntityState != EntityState.Detached))
                {
                    
    this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
                }
                
    else
                {
                    
    this.ObjectContext.Products.AddObject(product);
                }
            }

            
    public void UpdateProduct(Product currentProduct)
            {
                
    this.ObjectContext.Products.AttachAsModified(currentProduct, this.ChangeSet.GetOriginal(currentProduct));
            }

            
    public void DeleteProduct(Product product)
            {
                
    if ((product.EntityState == EntityState.Detached))
                {
                    
    this.ObjectContext.Products.Attach(product);
                }
                
    this.ObjectContext.Products.DeleteObject(product);
            }

            
    public IQueryable<Product> GetProductsByCategoryId(int categoryId)
            {
                
    return this.ObjectContext.Products.Where(p => p.CategoryID == categoryId);
            }
        }
    }



    MyDomainService.metadata.cs

    代码
    /*
     * [MetadataTypeAttribute()] - 指定类的元数据对象
     * [Include] - 生成的客户端上下文包含此字段
     * [Exclude] - 生成的客户端上下文不包含此字段
     * [Composition] - 指定字段为关联数据,即父实体增删改查时,此关联数据也会做相应的变化。指定此 Attribute 后,需显式指定其为 [Include]
     * [Editable(true)], [Editable(false)] - 指定字段是否可编辑
     
    */

    namespace Silverlight40.Web.Model
    {
        
    using System;
        
    using System.Collections.Generic;
        
    using System.ComponentModel;
        
    using System.ComponentModel.DataAnnotations;
        
    using System.Data.Objects.DataClasses;
        
    using System.Linq;
        
    using System.ServiceModel.DomainServices.Hosting;
        
    using System.ServiceModel.DomainServices.Server;

        [MetadataTypeAttribute(
    typeof(Category.CategoryMetadata))]
        
    public partial class Category
        {
            
    internal sealed class CategoryMetadata
            {
                
    private CategoryMetadata()
                {
                }

                [Key()]
                
    public int CategoryID { getset; }

                [Display(Name 
    = "类别名称")] // 显示用
                public string CategoryName { getset; }

                
    public string Description { getset; }

                [Exclude]
                
    public byte[] Picture { getset; }

                [Include]
                
    // [Composition]
                public EntityCollection<Product> Products { getset; }
            }
        }

        [MetadataTypeAttribute(
    typeof(Product.ProductMetadata))]
        
    public partial class Product
        {
            
    internal sealed class ProductMetadata
            {
                
    private ProductMetadata()
                {
                }

                
    public Category Category { getset; }

                
    public Nullable<int> CategoryID { getset; }

                
    public bool Discontinued { getset; }

                
    public EntityCollection<Order_Detail> Order_Details { getset; }

                [Display(Order 
    = 0, Name = "产品ID")]
                
    public int ProductID { getset; }

                [Display(Order 
    = 1, Name = "产品名称")]
                
    public string ProductName { getset; }

                
    public string QuantityPerUnit { getset; }

                
    public Nullable<short> ReorderLevel { getset; }

                
    public Supplier Supplier { getset; }

                
    public Nullable<int> SupplierID { getset; }

                
    public Nullable<decimal> UnitPrice { getset; }

                
    public Nullable<short> UnitsInStock { getset; }

                
    public Nullable<short> UnitsOnOrder { getset; }
            }
        }
    }


    客户端:
    DomainDataSourceDemo.xaml

    代码
    <!--
        System.Windows.Controls.DomainServices 程序集的默认位置:
        C:\Program Files\Microsoft SDKs\RIA Services\v1.0\Libraries\Silverlight\System.Windows.Controls.DomainServices.dll
    -->
    <navigation:Page x:Class="Silverlight40.WCFRIAServices.DomainDataSourceDemo" 
               xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               xmlns:sdk
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
               xmlns:riaControls
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" 
               xmlns:my
    ="clr-namespace:Silverlight40.Web.Service"
               Title
    ="DomainDataSourceDemo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">

                
    <!--
                    用于演示添加记录
                
    -->
                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Name="lblProductName4Add" Content="产品名称(添加用):" />
                    
    <TextBox Name="txtProductName4Add" Width="100" />
                    
    <Button Name="btnAdd" Content="新增" Click="btnAdd_Click" />
                
    </StackPanel>

                
    <!--
                    用于演示查询记录
                
    -->
                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Name="lblProductName" Content="产品名称(查询用):" />
                    
    <TextBox Name="txtProductName" Width="100" />
                
    </StackPanel>

                
    <!--
                    用于演示显示记录,更新记录,删除记录
                    将 DataGrid 的数据源绑定到 DomainDataSource 对象上,相关的查询排序等逻辑在 DomainDataSource 对象内设置
                
    -->
                
    <sdk:DataGrid Name="dataGrid" Width="600" Height="300" AutoGenerateColumns="False" ItemsSource="{Binding ElementName=productDomainDataSource, Path=Data}">
                    
    <sdk:DataGrid.Columns>
                        
    <sdk:DataGridTextColumn Header="供应商ID" Binding="{Binding SupplierID}" IsReadOnly="True" />
                        
    <sdk:DataGridTextColumn Header="产品类别ID" Binding="{Binding CategoryID}" IsReadOnly="True" />
                        
    <sdk:DataGridTextColumn Header="产品ID" Binding="{Binding ProductID}" IsReadOnly="True" />
                        
    <sdk:DataGridTextColumn Header="产品名称" Binding="{Binding ProductName}" />
                        
    <sdk:DataGridTemplateColumn Header="删除">
                            
    <sdk:DataGridTemplateColumn.CellTemplate>
                                
    <DataTemplate>
                                    
    <Grid>
                                        
    <Button Name="btnDelete" Content="删除" Click="btnDelete_Click" />
                                    
    </Grid>
                                
    </DataTemplate>
                            
    </sdk:DataGridTemplateColumn.CellTemplate>
                        
    </sdk:DataGridTemplateColumn>
                    
    </sdk:DataGrid.Columns>
                
    </sdk:DataGrid>
                
                
    <!--
                    将 DataPager 的数据源绑定到 DomainDataSource 对象上,即可实现服务端分页
                
    -->
                
    <sdk:DataPager Name="dataPager" Width="600" Height="30" PageSize="5" Source="{Binding ElementName=productDomainDataSource, Path=Data}" />
                
                
    <Button Name="btnSave" Content="保存" Click="btnSave_Click" />
                
            
    </StackPanel>

            
    <!--
                DomainDataSource - 一种数据源控件,通过一个 Domain 上下文关联 UI 和 WCF RIA Services。其所有查询操作均在服务端完成
                    QueryName - 指定查询方法
                    AutoLoad - 是否自动加载数据
                    FilterOperator - 各个 FilterDescriptor 间的逻辑关系。“And”或“Or”
            
    -->
            
    <riaControls:DomainDataSource Name="productDomainDataSource" QueryName="GetProductsByCategoryIdQuery" AutoLoad="True" FilterOperator="Or">

                
    <!--
                    指定数据上下文,来自 Silverlight40.Web.Service.MyDomainContext
                
    -->
                
    <riaControls:DomainDataSource.DomainContext>
                    
    <my:MyDomainContext />
                
    </riaControls:DomainDataSource.DomainContext>

                
    <!--
                    指定查询参数,为 GetProductsByCategoryId 方法传递参数,参数名:categoryId,参数值:1
                
    -->
                
    <riaControls:DomainDataSource.QueryParameters>
                    
    <riaControls:Parameter ParameterName="categoryId" Value="1" />
                
    </riaControls:DomainDataSource.QueryParameters>

                
    <!--
                    指定排序逻辑,按 SupplierID 字段正序排序
                
    -->
                
    <riaControls:DomainDataSource.SortDescriptors>
                    
    <riaControls:SortDescriptor Direction="Ascending" PropertyPath="SupplierID" />
                
    </riaControls:DomainDataSource.SortDescriptors>

                
    <!--
                    指定分组逻辑,按 SupplierID 字段分组显示
                
    -->
                
    <riaControls:DomainDataSource.GroupDescriptors>
                    
    <riaControls:GroupDescriptor PropertyPath="SupplierID" />
                
    </riaControls:DomainDataSource.GroupDescriptors>

                
    <!--
                    指定过滤逻辑,筛选逻辑为:ProductName 字段数据包含“a”或者 ProductName 字段数据包含 txtProductName.Text 中的内容
                
    -->
                
    <riaControls:DomainDataSource.FilterDescriptors>
                    
    <riaControls:FilterDescriptor Operator="Contains" PropertyPath="ProductName" Value="a" />
                    
    <riaControls:FilterDescriptor Operator="Contains" PropertyPath="ProductName" Value="{Binding ElementName=txtProductName, Path=Text}" />
                
    </riaControls:DomainDataSource.FilterDescriptors>

            
    </riaControls:DomainDataSource>
        
    </Grid>
    </navigation:Page>


    DomainDataSourceDemo.xaml.cs

    代码
    /*
     * 演示通过 DomainDataSource 实现数据的添加、查询、更新和删除操作,以及服务端的查询、排序和分页等逻辑 
     
    */

    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.Windows.Navigation;

    using Silverlight40.Web.Model;
    using System.ServiceModel.DomainServices.Client;

    namespace Silverlight40.WCFRIAServices
    {
        
    public partial class DomainDataSourceDemo : Page
        {
            
    public DomainDataSourceDemo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                
    // DomainDataSource.SubmitChanges() - 提交数据的变化
                
    // DomainDataSource.SubmittingChanges - SubmitChanges() 执行前所触发的事件
                
    // DomainDataSource.SubmittedChanges - SubmitChanges() 执行后所触发的事件
                
    // DomainDataSource.Load() - 加载查询结果

                productDomainDataSource.SubmittingChanges 
    += new EventHandler<SubmittingChangesEventArgs>(productDomainDataSource_SubmittingChanges);
                productDomainDataSource.SubmittedChanges 
    += new EventHandler<SubmittedChangesEventArgs>(productDomainDataSource_SubmittedChanges);
            }

            
    private void productDomainDataSource_LoadedData(object sender, LoadedDataEventArgs e)
            {
                
    if (e.HasError)
                {
                    System.Windows.MessageBox.Show(e.Error.ToString(), 
    "Load Error", System.Windows.MessageBoxButton.OK);
                    e.MarkErrorAsHandled();
                }
            }

            
    private void btnSave_Click(object sender, RoutedEventArgs e)
            {
                productDomainDataSource.SubmitChanges();
            }

            
    void productDomainDataSource_SubmittingChanges(object sender, SubmittingChangesEventArgs e)
            {
                MessageBox.Show(
    "Submitting");
            }

            
    void productDomainDataSource_SubmittedChanges(object sender, SubmittedChangesEventArgs e)
            {
                
    if (e.HasError)
                {
                    MessageBox.Show(e.Error.ToString());
                }
                
    else
                {
                    MessageBox.Show(
    "Submitted");
                    productDomainDataSource.Load();
                }
            }

            
    private void btnAdd_Click(object sender, RoutedEventArgs e)
            {
                
    // DomainDataSource.DomainContext - 数据上下文对象 [System.ServiceModel.DomainServices.Client.DomainContext 类型]
                
    // DomainContext.EntityContainer - 数据上下文对象中的全部实体 [System.ServiceModel.DomainServices.Client.EntityContainer 类型]
                
    // EntityContainer.GetEntitySet<T>() - 获取指定类型的实体数据

                EntitySet
    <Product> products = productDomainDataSource.DomainContext.EntityContainer.GetEntitySet<Product>();
                Product product 
    = new Product();
                product.ProductName 
    = txtProductName4Add.Text;
                product.CategoryID 
    = 1;
                product.SupplierID 
    = 1;
                products.Add(product);

                productDomainDataSource.SubmitChanges();
            }

            
    private void btnDelete_Click(object sender, RoutedEventArgs e)
            {
                EntitySet
    <Product> products = productDomainDataSource.DomainContext.EntityContainer.GetEntitySet<Product>();
                Product product 
    = dataGrid.SelectedItem as Product;
                products.Remove(product);

                productDomainDataSource.SubmitChanges();
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    【异常】No ManagedConnections available within configured blocking timeout
    【异常】Caused by: java.lang.ClassNotFoundException: org.springframework.dao.DataIntegrityViolationException
    【Redis】:Jedis 使用
    【异常】INFO: TopologyManager: EndpointListener changed ...
    【Java】JDK类 CountDownLatch
    【WEB】一个简单的WEB服务器
    【JAVA】Socket 编程
    【JBOSS】 JBOSS目录结构
    [SE0]简单的搜索引擎原理
    【ORACLE】 表空间信息
  • 原文地址:https://www.cnblogs.com/webabcd/p/1850959.html
Copyright © 2011-2022 走看看