• 稳扎稳打Silverlight(58) 4.0通信之WCF RIA Services: 通过 Domain Service, 以 MVVM 模式实现数据的添加、删除、修改和查询


    [索引页]
    [源码下载]


    稳扎稳打Silverlight(58) - 4.0通信之WCF RIA Services: 通过 Domain Service, 以 MVVM 模式实现数据的添加、删除、修改和查询



    作者:webabcd


    介绍
    Silverlight 4.0 之 WCF RIA Services:DomainService 和 MVVM


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


    示例
    演示如何通过 Domain Service, 以 MVVM 模式实现数据的添加、删除、修改和查询
    1、服务端
    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; }
            }
        }
    }



    2、客户端
    ProductViewModel.cs

    代码
    /*
     * 演示:通过 Domain Service, 以 MVVM 模式实现数据的添加、删除、修改和查询
     * 此类为 MVVM 中的 ViewModel
     
    */

    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    using Silverlight40.Web.Model;
    using System.Collections.ObjectModel;
    using Silverlight40.Web.Service;
    using System.ComponentModel;
    using System.ServiceModel.DomainServices.Client;
    using System.Collections.Generic;

    namespace Silverlight40.WCFRIAServices.DomainServiceAndMVVM
    {
        
    public class ProductViewModel
        {
            
    public ObservableCollection<Product> Data { getset; }
           
            
    private MyDomainContext _context;

            
    public ProductViewModel()
            {
                Data 
    = new ObservableCollection<Product>();

                LoadData();
            }

            
    private void LoadData()
            {
                _context 
    = new MyDomainContext();

                EntityQuery
    <Product> query = _context.GetProductsQuery().OrderByDescending(p => p.ProductID);

                
    /*
                 * System.ServiceModel.DomainServices.Client.LoadOperation - 用于异步加载
                 * System.ServiceModel.DomainServices.Client.InvokeOperation - 用于异步调用
                 * System.ServiceModel.DomainServices.Client.SubmitOperation - 用于异步提交
                 
    */

                LoadOperation
    <Product> lo = _context.Load(query);

                lo.Completed 
    += delegate
                {
                    Data.Clear();
                    
    foreach (Product p in lo.Entities)
                    {
                        Data.Add(p);
                    }
                };
            }


            
    public ICommand FilterCommand
            {
                
    get { return new FilterCommand(this); }
            }
            
    public ICommand InsertCommand
            {
                
    get { return new InsertCommand(this); }
            }
            
    public ICommand DeleteCommand
            {
                
    get { return new DeleteCommand(this); }
            }
            
    public ICommand UpdateCommand
            {
                
    get { return new UpdateCommand(this); }
            }


            
    // 检索数据
            public void Filter(string productName)
            {
                EntityQuery
    <Product> query = _context.GetProductsQuery().Where(p => p.ProductName.Contains(productName));

                LoadOperation
    <Product> lo = _context.Load(query);

                lo.Completed 
    += delegate
                {
                    Data.Clear();

                    
    foreach (Product p in lo.Entities)
                    {
                        Data.Add(p);
                    }
                };
            }

            
            
    // 插入数据
            public void Insert(string productName)
            {            
                EntitySet
    <Product> products = _context.EntityContainer.GetEntitySet<Product>();
                Product product 
    = new Product();
                product.ProductName 
    = productName;
                product.CategoryID 
    = 1;
                product.SupplierID 
    = 1;
                products.Add(product);

                _context.SubmitChanges(OnInsertCompleted, product);
            }
            
    private void OnInsertCompleted(SubmitOperation so)    
            {
                
    if (!so.HasError)
                {
                    Data.Insert(
    0, so.UserState as Product);
                }
            }


            
    // 删除数据
            public void Delete(List<Product> products)
            {
                EntitySet
    <Product> productsOriginal = _context.EntityContainer.GetEntitySet<Product>();
                
    foreach (Product product in products)
                {
                    productsOriginal.Remove(product);
                }

                _context.SubmitChanges(OnDeleteCompleted, products);
            }
            
    private void OnDeleteCompleted(SubmitOperation so)
            {
                
    if (!so.HasError)
                {
                    List
    <Product> products = so.UserState as List<Product>;
                    
    foreach (Product product in products)
                    {
                        Data.Remove(product);
                    }
                }
            }


            
    // 更新数据
            public void Update()
            {
                _context.SubmitChanges(OnUpdateCompleted, 
    null);
            }
            
    private void OnUpdateCompleted(SubmitOperation so)
            {
                
    if (!so.HasError)
                {
                    MessageBox.Show(
    "更新成功");
                }
            }
        }
    }


    InsertCommand.cs

    代码
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace Silverlight40.WCFRIAServices.DomainServiceAndMVVM
    {
        
    /// <summary>
        
    /// 插入的 Command
        
    /// </summary>
        public class InsertCommand : ICommand
        {
            
    private ProductViewModel _viewModel;

            
    public InsertCommand(ProductViewModel viewModel)
            {
                _viewModel 
    = viewModel;
            }

            
    public bool CanExecute(object parameter)
            {
                
    return true;
            }

            
    public event EventHandler CanExecuteChanged;

            
    // 参数为:productName
            public void Execute(object parameter)
            {
                var productName 
    = (string)parameter;
                _viewModel.Insert(productName);
            }
        }
    }


    DeleteCommand.cs

    代码
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    using Silverlight40.Web.Model;
    using System.Collections.Generic;

    namespace Silverlight40.WCFRIAServices.DomainServiceAndMVVM
    {
        
    /// <summary>
        
    /// 删除的 Command
        
    /// </summary>
        public class DeleteCommand  : ICommand
        {
            
    private ProductViewModel _viewModel;

            
    public DeleteCommand(ProductViewModel viewModel)
            {
                _viewModel 
    = viewModel;
            }

            
    public bool CanExecute(object parameter)
            {
                
    return true;
            }

            
    public event EventHandler CanExecuteChanged;

            
    // 参数为:DataGrid.SelectedItems [System.Collections.IList 类型]
            public void Execute(object parameter)
            {
                var collection 
    = parameter as System.Collections.IList;
                var products 
    = new List<Product>();

                
    foreach (Product product in collection)
                {
                    products.Add(product);
                }

                _viewModel.Delete(products);
            }
        }
    }


    UpdateCommand.cs

    代码
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace Silverlight40.WCFRIAServices.DomainServiceAndMVVM
    {
        
    /// <summary>
        
    /// 更新的 Command
        
    /// </summary>
        public class UpdateCommand : ICommand
        {
            
    private ProductViewModel _viewModel;

            
    public UpdateCommand(ProductViewModel viewModel)
            {
                _viewModel 
    = viewModel;
            }

            
    public bool CanExecute(object parameter)
            {
                
    return true;
            }

            
    public event EventHandler CanExecuteChanged;

            
    public void Execute(object parameter)
            {
                _viewModel.Update();
            }
        }
    }


    FilterCommand.cs

    代码
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace Silverlight40.WCFRIAServices.DomainServiceAndMVVM
    {
        
    /// <summary>
        
    /// 查询的 Command
        
    /// </summary>
        public class FilterCommand : ICommand
        {
            
    private ProductViewModel _viewModel;

            
    public FilterCommand(ProductViewModel viewModel)
            {
                _viewModel 
    = viewModel;
            }

            
    public bool CanExecute(object parameter)
            {
                
    return true;
            }

            
    public event EventHandler CanExecuteChanged;

            
    // 参数为:productName
            public void Execute(object parameter)
            {
                var productName 
    = (string)parameter;
                _viewModel.Filter(productName);
            }
        }
    }
     


    Demo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.WCFRIAServices.DomainServiceAndMVVM.Demo" 
               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:vm
    ="clr-namespace:Silverlight40.WCFRIAServices.DomainServiceAndMVVM"
               Title
    ="Demo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">

                
    <!--
                    在 View 中引入 ViewModel
                
    -->
                
    <StackPanel.DataContext>
                    
    <vm:ProductViewModel />
                
    </StackPanel.DataContext>
                
                
    <!--
                    用于演示添加记录
                
    -->
                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Name="lblProductName4Add" Content="产品名称(添加用):" />
                    
    <TextBox Name="txtProductName4Add" Width="100" />
                    
    <Button Name="btnAdd" Content="新增" Command="{Binding InsertCommand}" CommandParameter="{Binding ElementName=txtProductName4Add, Path=Text }" />
                
    </StackPanel>

                
    <!--
                    用于演示查询记录
                
    -->
                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Name="lblProductName" Content="产品名称(查询用):" />
                    
    <TextBox Name="txtProductName" Width="100" />
                    
    <!--
                        如果 Command 需要传递多个参数,则可以
                            1、将 CommandParameter 绑定到一个容器控件,然后在 Command 中去遍历容器控件内的控件(破坏 ViewModel)
                            2、在 View 中调用 Command 之前构造一个复杂类型,再传递给 ViewModel(破坏 View)
                            3、ViewModel 中设置一个对象,其是 Model 层中的某个类的实例,同时此对象双向绑定到 View 上,这样这个复杂类型就可以通过 ViewModel 来传递
                    
    -->
                    
    <Button Name="btnFilter" Content="查询" Command="{Binding FilterCommand}" CommandParameter="{Binding ElementName=txtProductName, Path=Text }" />
                
    </StackPanel>

                
    <!--
                    用于演示显示记录
                
    -->
                
    <sdk:DataGrid Name="dataGrid" Width="600" Height="300" AutoGenerateColumns="False" ItemsSource="{Binding 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:DataGrid.Columns>
                
    </sdk:DataGrid>

                
    <!--
                    用于演示删除记录
                
    -->
                
    <Button Name="btnDelete" Content="删除选中(可多选)" Command="{Binding DeleteCommand}" CommandParameter="{Binding ElementName=dataGrid, Path=SelectedItems }" />

                
    <!--
                    用于演示更新记录
                
    -->
                
    <Button Name="btnSave" Content="保存全部" Command="{Binding UpdateCommand}" />
                
            
    </StackPanel>
        
    </Grid>
    </navigation:Page>



    OK
    [源码下载]

  • 相关阅读:
    冲刺的二阶段第五天
    第二阶段冲刺第四天
    冲刺第二阶段第三天
    《你的灯亮着吗》读书笔记三
    《你的灯亮着吗》读书笔记二
    《你的灯亮着吗》读书笔记一
    数1
    水王续
    输入法之体验
    返回一个二维整数数组中最大联通子数组的和
  • 原文地址:https://www.cnblogs.com/webabcd/p/1853976.html
Copyright © 2020-2023  润新知