谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持

简介:
在本篇文章上一部分 Order Processing 的例子中,我们看到原本已 Collection 形式定义的 DetailList 属性( public IList<TDetail> DetailList ),在 Data Contract 中却以 Array 的方式体现( public OrderDetail[] DetailList )。我们现在就来详细地讨论一下基于 Collection & Dictionary Data Contract

Data Contract for Collection

我们照例用例子来说明问题,在这里我们创建一个批量处理
OrderService,于是我们创建了一个OrderCollection Type:

namespace Artech.SpecialDataContract.Contract
{
    [DataContract]
    public class Order
    {
        [DataMember]
        public Guid OrderID
        getset; }

        [DataMember]
        public DateTime OrderDate
        getset; }
    }


    public class OrderCollection : List<Order>
    {

    }

}

下面是Service Contract的定义:

 

namespace Artech.SpecialDataContract.Contract
{
    [ServiceContract]
    public interface IOrderManager
    {
        [OperationContract(Name = "ProcessWithCollection")]
        void Process(OrderCollection orders);
}

面是OrderCollection XSD中的呈现:

<? xml version="1.0" encoding="utf-8"  ?>
< xs:schema  elementFormDefault ="qualified"  targetNamespace ="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"
    xmlns:xs
="http://www.w3.org/2001/XMLSchema"  xmlns:tns ="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"
    xmlns:ser
="http://schemas.microsoft.com/2003/10/Serialization/" >
   < xs:import  schemaLocation ="http://artech/Artech.SpecialDataContract/OrderManagerService.svc?xsd=xsd1"
          namespace
="http://schemas.microsoft.com/2003/10/Serialization/"   />
   < xs:complexType  name ="ArrayOfOrder" >
     < xs:sequence >
       < xs:element  minOccurs ="0"  maxOccurs ="unbounded"  name ="Order"  nillable ="true"  type ="tns:Order"   />
     </ xs:sequence >
   </ xs:complexType >
   < xs:element  name ="ArrayOfOrder"  nillable ="true"  type ="tns:ArrayOfOrder" />
   < xs:complexType
name ="Order" >
     < xs:sequence >
       < xs:element  minOccurs ="0"  name ="OrderDate"  type ="xs:dateTime" />
       < xs:element
minOccurs ="0"  name ="OrderID"  type ="ser:guid" />
     </ xs:sequence >
   </ xs:complexType >
   < xs:element
name ="Order"  nillable ="true"  type ="tns:Order" />
</ xs:schema >

加上通过Add Service Reference默认生成的Class,我们可以很清楚地看出Collection是以Array的形式呈现的(Artech.SpecialDataContract.Client.OrderManagerService.Order[] orders):

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="OrderManagerService.IOrderManager")]
     public  interface IOrderManager 
        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOrderManager/ProcessWithCollection", ReplyAction="http://tempuri.org/IOrderManager/ProcessWithCollectionResponse")]
        void ProcessWithCollection(Artech.SpecialDataContract.Client.OrderManagerService.Order[] orders);
}

因为Array相对很Common的数据类型,基本上所有的厂商均提供了对Array的支持,这也是WCF在通过Add Service Reference生成Client端代码的时候,会生成Array的原因。不过并不是我们只有唯一的选择,事实上VS为此提供了扩展,允许我们对于基于Collection Data Contract生成我们需要的各种类型,我们只需要在Add Service Reference的时候选择“Configure Service Reference”进行相应的配置:

通过上面的截图,我们发现在Collection Type一项我们有若干选项,我们可以选择我们希望生成的数据类型:ArrayArrayListLinkedListGeneric ListCollectionBindingList 

Data Contract for Dictionary

前面的内容,我们分别讨论了基于GenericCollectionData Contract,接下来,我们来讨论最后一个特殊的数据类型的Data ContractDictionary

延续上面的Order Batch Processing的例子,不过我们现在处理的不是一个OrderCollection对象,而是一个Dictionary对象,线面是Service ContractOrder的定义:

namespace Artech.SpecialDataContract.Contract
{
    [ServiceContract]
    public interface IOrderManager
    {
        [OperationContract(Name = "ProcessWithCollection")]
        void Process(OrderCollection orders);

        [OperationContract(Name = "ProcessWithDictionary")]
        void Process(IDictionary<Guid, Order> orders);
    }

}

 

    [DataContract]
     public  class Order
     {
        [DataMember]
        public Guid OrderID
        getset; }

        [DataMember]
        public DateTime OrderDate
        getset; }
    }

闲话少说,我们来看XSD

<? xml version="1.0" encoding="utf-8" ?>
< xs:schema  elementFormDefault ="qualified"  targetNamespace ="http://schemas.microsoft.com/2003/10/Serialization/Arrays"  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns:tns ="http://schemas.microsoft.com/2003/10/Serialization/Arrays"  xmlns:ser ="http://schemas.microsoft.com/2003/10/Serialization/" >
   < xs:import  schemaLocation ="http://artech/Artech.SpecialDataContract/OrderManagerService.svc?xsd=xsd1"  namespace ="http://schemas.microsoft.com/2003/10/Serialization/" />
   < xs:import  schemaLocation ="http://artech/Artech.SpecialDataContract/OrderManagerService.svc?xsd=xsd2"  namespace ="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract" />
   < xs:complexType  name ="ArrayOfKeyValueOfguidOrder_SkVQi6O3" >
     < xs:annotation >
       < xs:appinfo >
         < IsDictionary  xmlns ="http://schemas.microsoft.com/2003/10/Serialization/" >true </ IsDictionary >
       </ xs:appinfo >
     </ xs:annotation >
     < xs:sequence >
       < xs:element  minOccurs ="0"  maxOccurs ="unbounded"  name ="KeyValueOfguidOrder_SkVQi6O3" >
         < xs:complexType >
           < xs:sequence >
             < xs:element  name ="Key"  type ="ser:guid" />
             < xs:element  name ="Value"  nillable ="true"  type ="q1:Order"  xmlns:q1 ="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract" />
           </ xs:sequence >
         </ xs:complexType >
       </ xs:element >
     </ xs:sequence >
   </ xs:complexType >
   < xs:element  name ="ArrayOfKeyValueOfguidOrder_SkVQi6O3"  nillable ="true"  type ="tns:ArrayOfKeyValueOfguidOrder_SkVQi6O3" />
</ xs:schema >

Data Contract的名称为ArrayOfKeyValueOfguidOrder_SkVQi6O3=ArrayOfKeyValueOf+guidKey的类型)+OrderValue+_SkVQi6O3Hash Value)。从该XSD的结构我们不难看出,只是一个数组,每个元素为Key-Value pair

我们照例看看通过Add Service Reference方式生成的Clientcode中的对应的定义:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="OrderManagerService.IOrderManager")]
     public  interface IOrderManager  {               
        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOrderManager/ProcessWithDictionary", ReplyAction="http://tempuri.org/IOrderManager/ProcessWithDictionaryResponse")]
        void ProcessWithDictionary(System.Collections.Generic.Dictionary<System.Guid, Artech.SpecialDataContract.Client.OrderManagerService.Order> orders);
    }

生成的是一个System.Collections.Generic.Dictionary类型。同Collection一样,也依然可以有多种选择:


[原创]谈谈WCF中的Data Contract(1):Data Contract Overview
[原创]谈谈WCF中的Data Contract(2):WCF Data Contract对Generic的支持
[原创]谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持
[原创]谈谈WCF中的Data Contract(4):WCF Data Contract Versioning


作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
2月前
Transparent Data Encryption Data Dynamic and Data Dictionary Views You can query a set of dynamic and data dictionary views to find more information about Transparent Data Encryption (TDE) data.
Transparent Data Encryption Data Dynamic and Data Dictionary Views You can query a set of dynamic and data dictionary views to find more information about Transparent Data Encryption (TDE) data.
21 2
|
2月前
|
关系型数据库 MySQL
MySQL 报错 [ERROR] [FATAL] InnoDB: Table flags are 0 in the data dictionary but the flags in file
MySQL 报错 [ERROR] [FATAL] InnoDB: Table flags are 0 in the data dictionary but the flags in file
547 0
|
2月前
|
Oracle 安全 关系型数据库
3.6.7 Encrypted Sensitive Credential Data in the Data Dictionary
You can encrypt sensitive credential data in the SYS.LINK$ and SYS.SCHEDULER$_CREDENTIAL system tables. By default, the credential data in the SYS.LINK$ and SYS.SCHEDULER$_CREDENTIAL system tables is obfuscated. However, because of the availability of many types of de-obfuscation algorithms, Oracle
21 0
|
存储 关系型数据库 数据库
Data dictionary header(2) --系统表空间结构(三十四)
Data dictionary header(2) --系统表空间结构(三十四)
|
存储 SQL 缓存
MySQL 深潜 - 一文详解 MySQL Data Dictionary
在 MySQL 8.0 之前,Server 层和存储引擎(比如 InnoDB)会各自保留一份元数据(schema name, table definition 等),不仅在信息存储上有着重复冗余,而且可能存在两者之间存储的元数据不同步的现象。不同存储引擎之间(比如 InnoDB 和 MyISAM)有着不同的元数据存储形式和位置(.FRM, .PAR, .OPT, .TRN and .TRG files),造成了元数据无法统一管理。此外,将元数据存放在不支持事务的表和文件中,使得 DDL 变更不会是原子的,crash recovery 也会成为一个问题。
826 0
MySQL 深潜 - 一文详解 MySQL Data Dictionary
|
存储 SQL 缓存
MySQL 深潜 - 一文详解 MySQL Data Dictionary
在 MySQL 8.0 之前,Server 层和存储引擎(比如 InnoDB)会各自保留一份元数据(schema name, table definition 等),不仅在信息存储上有着重复冗余,而且可能存在两者之间存储的元数据不同步的现象。不同存储引擎之间(比如 InnoDB 和 MyISAM)有着不同的元数据存储形式和位置(.FRM, .PAR, .OPT, .TRN and .TRG files),造成了元数据无法统一管理。此外,将元数据存放在不支持事务的表和文件中,使得 DDL 变更不会是原子的,crash recovery 也会成为一个问题。
MySQL 深潜 - 一文详解 MySQL Data Dictionary
|
存储 SQL 缓存
MySQL 深潜 - 一文详解 MySQL Data Dictionary
# 背景 在 MySQL 8.0 之前,Server 层和存储引擎(比如 InnoDB)会各自保留一份元数据(schema name, table definition 等),不仅在信息存储上有着重复冗余,而且可能存在两者之间存储的元数据不同步的现象。不同存储引擎之间(比如 InnoDB 和 MyISAM)有着不同的元数据存储形式和位置(.FRM, .PAR, .OPT, .TRN and .TR
363 0