前言

昨天早上去医院做入职体检,被告知要预约,本以为是要排队,我连视频都准备好了。。。结果就回来了。下午去了新公司那边找房子,2了,因为公司提供了班车列表,我既然就只在班车所经过的几个地方找,却遗漏了公司附近这个重要的地址。最后找了一个“江景房”,上阳台就能看到钱塘江。价格和现在的比翻了一倍,累了,不想找了。

有朋友让我把标题前缀“年前辞职”4个字拿了,好吧,我承认,我就是靠这个吸引一部分眼球的。

第六集 WCF DataContract & DataMember (WCF的Data和DataMember)

这些天写下来关于那个mex还是有点困惑,早上在stackoverflow上搜到一个回答,感觉写得挺好的,在此拿出来分享一下。地址:http://stackoverflow.com/questions/21522493/what-was-the-difference-between-wsdl-mex-endpoint-in-wcf 。或许如果你有WebService的经验,理解起来会更轻松一些。站在使用者的角度,我试着拿掉了endpoint有关mex的定义,以及注释了behaviors节点,然后访问http://localhost:8080/ 页面给了我这么一个提示:

还是回到了最初。

还有一点,stackoverflow回答中向我们传递了一个意思,关于WCF,就像他这么用就行,因为,WCF本身还有更多的复杂有趣的东西等我们去开发实践。

今天讲第六集,这两个是用来修饰需要序列化的实体类的特性,并且也会涉及到KnownType 看了之后觉得是一个很有用的特性。

首先,我们来实现一个EmployeeService,主要的作用是用来根据id查询Employee,以及向数据库插入Employee。下面开始介绍:

数据库部分

我们新建了一张表,叫Employee,左边是表结构,右边是内容,Id列没有用自增。

然后新建了2个存储过程,一个spGetEmployeeById,一个SaveEmployee

select * from Employee where Id= @id;
insert into Employee (Id ,Name,Gender,DateOfBirth) values (@id ,@name,@gender,@dateOfBirth)

其他定义部分的就写出来了。

服务部分

     public class Employee
{
private int _id;
private string _name;
private bool _gender;
private DateTime _dateOfBirth; public int Id
{
get { return _id; }
set { this._id = value; }
}
public String Name
{
get { return _name; }
set { this._name = value; }
}
public bool Gender
{
get { return _gender; }
set { this._gender = value; }
}
public DateTime DateOfBirth
{
get { return _dateOfBirth; }
set { this._dateOfBirth = value; }
}
}

上面是Employee 类的定义,有人可能会纳闷,为什么要额外定义个私有变量,C#这个人性化的语言不是只要写get;set就ok?开始我也有这个样的疑惑。但其实,这里是为了说明问题,特地这么写的。

public class EmployeeService : IEmployeeService
{
public Employee GetEmployee(int id)
{
Employee emp = null;
var connStr = ConfigurationManager.ConnectionStrings["WCFEmployee"].ConnectionString;
using(var conn = new SqlConnection(connStr)) {
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "spGetEmployeeById";
cmd.Parameters.Add(new SqlParameter("id", id));
var reader = cmd.ExecuteReader();
if(!reader.HasRows) return emp;
emp = new Employee();
while(reader.Read()) {
emp.Id = Convert.ToInt32(reader["Id"]);
emp.Name = reader["Name"].ToString();
emp.Gender = Convert.ToBoolean(reader["Gender"]);
emp.DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]);
}
}
return emp;
} public void SaveEmployee(Employee emp)
{
var connStr = ConfigurationManager.ConnectionStrings["WCFEmployee"].ConnectionString;
using(var conn = new SqlConnection(connStr)) {
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "spSaveEmployee";
cmd.Parameters.Add(new SqlParameter("id", emp.Id));
cmd.Parameters.Add(new SqlParameter("name", emp.Name));
cmd.Parameters.Add(new SqlParameter("gender", emp.Gender));
cmd.Parameters.Add(new SqlParameter("dateOfBirth", emp.DateOfBirth));
cmd.ExecuteNonQuery();
}
}
}

上面是EmployeeService.cs 用了最基本的ADO.net操作。

再建一个控制台程序,来托管这个服务,运行成功。

客户端调用

新建一个WebForm的客户端,实现如下效果,代码不贴了,都很基本。

在id框里面输入id,查询这个id的对应的信息。

没有查到给提示。

输入信息点保存提示,保存到数据库。

写完之后,一切运行顺利。在介绍下面东西之前,我们先介绍几个概念

  • 什么是Serialization和Deserialization

从WCF角度来说,Serialization(序列化)是个转换的过程,它把一个实体类转换为XML,反过来讲,通过XML文件,得到一个实体类的过程叫Deserialization(反序列化)。

  • 序列化有什么用

这里有一篇 stackoverflow 上的问答,大致意思是说用来存储以及传输数据用的。and 序列化是必须的

如果不特殊指定,WCF用DataContractSerializer来序列化object(终于出现标题上的关键字了)。

为了序列化Employee,我们可以用SerializableAttribute 或者 DataContractAttribute特性修饰这个类。但看看上面的Employee类,我们并没有加上那两个特性。那是因为,从framework 3.5开始,如果我们没有使用DataContract 或者DataMember 特性,那么WCF的DataContractSerializer会自动把所有的public属性按照字典序的顺序序列化。让我们访问http://localhost:8080/?wsdl 来看看:

搜索datacontract

然后在地址栏里面输入后面的schemaLocation的值 http://localhost:8080/?xsd=xsd2 回车:

Employee是一个complexType,下面的sequence里面有他的四个属性。这是默认生成的schema。

上面说了我们可以通过给一个类加Serializable或者是DataContract特性来显式标记一个需要序列化的类,下面我们来看看这两种方式有什么不同。

先看用Serializable标记的:

我们看到,所有带下划线的私有变量都被序列化了。

再看看用DataContract的效果:

由于我们只给类标记了DataContract特性,没有任何字段被序列化了。。。(因为没有序列化字段,客户端在调用这个类的时候也是无法获取到对应的属性的。如图:

其实,DataContract应该是和DataMember配合使用。并且,这也是WCF推荐的做法。下面我们来实现一个。

在此之前,我们先看一下DataMember特性所包含的属性:链接

通过这些属性,我们可以自由的控制他们在序列化时的名称,顺序等等。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text; namespace EmployeeService
{
[DataContract]
public class Employee
{
private int _id;
private string _name;
private bool _gender;
private DateTime _dateOfBirth; [DataMember(Order = )]
public int Id
{
get { return _id; }
set { this._id = value; }
}
[DataMember(Order = )]
public String Name
{
get { return _name; }
set { this._name = value; }
}
[DataMember(Order = )]
public bool Gender
{
get { return _gender; }
set { this._gender = value; }
}
[DataMember(Order = )]
public DateTime DateOfBirth
{
get { return _dateOfBirth; }
set { this._dateOfBirth = value; }
}
}
}

通过添加DataMember特性,字段回来了,并且序列化的顺序也按照我的赋予的排好了。

总结一下,用DataContract 和 DataMember来控制我们需要序列化的对象。

下面还有KnowTypeAttribute的知识点,貌似有不少东西好写,还是另开一篇吧。。。文章长了看的人就更少了。。。

Thank you!

年前辞职-WCF入门(6)的更多相关文章

  1. 年前辞职-WCF入门学习(1,2)

    前言 周一的时候辞职了,离开了从12年毕业后8月份开始一直到现在的公司. 辞职之后当然是玩.玩了若干天的游戏,真的是没日没夜啊,但是玩的太坑,怒删游戏.话说上次玩还是在14年7月份.下次还是过年回家再 ...

  2. 年前辞职-WCF入门学习(5)

    前言 第五集比较简单,视频也只有7分多钟,但是用处还是挺大的.下面我会介绍. 本来想第六集一起介绍的,后来发现第六集内容比较多,有半个多小时,就不一起了.网站规定6小时内只能发布一篇文章到首页,,那我 ...

  3. 年前辞职-WCF入门学习(4)

    前言 上一篇的学习中碰到一个问题,用地址http://localhost:8080/mex 访问元数据的时候一直提示400 bad request 错误,因为时间太晚了,查了好几遍代码,也没有发现问题 ...

  4. 年前辞职-WCF入门学习(3)

    前言 [2了,刚写好的,手贱,点了删除,还真TMD的删除了,只好重写] 今天周六,去同事家聚了一个餐,感觉各种豪华. 废话不多说,前两集大致介绍了一下什么是WCF以及和WCF相关的WebService ...

  5. 学习WCF入门的第一个实例

    一.概述 WCF说白了就是一个基于终结点的通信手段!就是Service端提供一定的功能实现,然后暴露出一个或多个终结点,Client端调用Service端的功能(可以理解为调用一个函数),那么Clie ...

  6. WCF入门教程(五)配置文件

    WCF入门教程(五)配置文件 服务协定以及实现写好后,需要将相关服务公布出去,就需要HOST来承载,供客户端来调用. 承载服务有两种方式,一种通过配置文件,一种通过代码进行配置.上一章已经介绍了代码方 ...

  7. WCF入门教程(四)通过Host代码方式来承载服务

    WCF入门教程(四)通过Host代码方式来承载服务 之前已经讲过WCF对外发布服务的具体方式. WCF入门教程(一)简介 Host承载,可以是web,也可以是控制台程序等等.比WebService有更 ...

  8. WCF入门教程(三)定义服务协定--属性标签

    WCF入门教程(三)定义服务协定--属性标签 属性标签,成为定义协议的主要方式.先将最简单的标签进行简单介绍,以了解他们的功能以及使用规则. 服务协定标识,标识哪些接口是服务协定,哪些操作时服务协定的 ...

  9. WCF入门教程(二)如何创建WCF服务

    WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...

随机推荐

  1. libc.so.6被删后导致系统无法使用的原因及解决方法

    记一次升级glibc库发生的错误 今天给glibc库升级,发生了一件让我吓出一声汗的事情,我把动态库中的libc.so.6给删了,瞬间所有的非系统命令都无法使用,使用就报错 当时就吓尿了,生产环境被我 ...

  2. java截取日期范围并计算相差月数

    前两天,媳妇单位让整理excel的某一个单元格内两个日期范围的相差月数,本人对excel操作不是很熟练,便写了个小程序计算了一下,原始需求如下: 计算投资期限的范围,并得到期限范围的相差月数 思路1: ...

  3. 递归:codevs 1251 括号

    codevs 1251 括号  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold   题目描述 Description 计算乘法时,我们可以添加括号,来改变相乘的顺 ...

  4. HDU 4121 Xiangqi --模拟

    题意: 给一个象棋局势,问黑棋是否死棋了,黑棋只有一个将,红棋可能有2~7个棋,分别可能是车,马,炮以及帅. 解法: 开始写法是对每个棋子,都处理处他能吃的地方,赋为-1,然后判断将能不能走到非-1的 ...

  5. 【Java基础】java 获得本日,本周,本月的时间戳区间

    如果涉及到统计的话,可能会经常用到.很简单的基础知识. 1.getTimestampByOffsetDay public static long getTimestampByOffsetDay(int ...

  6. java 20 - 6 加入了异常处理的字节输出流的操作

    昨天坐了十几个钟的车回家,累弊了.... ————————————割掉疲劳————————————— 前面的字节输出流都是抛出了异常不管,这次的加入了异常处理: 首先还是创建一个字节输出流对象,先给它 ...

  7. Android ant自动打包 crunch 报错

    解决办法: 修改SDK_HOME/tool/ant/build.xml. <property name="aapt.ignore.assets" value="&l ...

  8. Android 手势识别类 ( 一 ) GestureDetector 基本介绍

    为了加强鼠标响应事件,Android提供了GestureDetector手势识别类.通过GestureDetector.OnGestureListener来获取当前被触发的操作手势(Single Ta ...

  9. Managing the Lifecycle of a Service

    service的生命周期,从它被创建开始,到它被销毁为止,可以有两条不同的路径: A started service 被开启的service通过其他组件调用 startService()被创建. 这种 ...

  10. C# 无边框窗体边框阴影效果

    通过下面代码在构造函数中调用方法 SetShadow(); 即可实现无边框窗体的阴影效果了 需要添加命名空间 using System.Runtime.InteropServices; private ...