WCF和Entity framework 发现的性能问题

最近在用entity framework 和 WCF结合做服务端,偶然发现一个问题,就是数据传输对象(DTO)的容量问题,我的项目方案是把数据访问层封装为WCF部署在外网服务器上供客户端调 用.我发现传输速度没有想象的那么好,简直就是不堪入目,终于有一天我发现问题的所在,就是edmx生成的实体类和自己手写实体类的区别,我用 District这张表来做演示,表中一共有5个字段,废话不多说,先看一代码,
下面是edmx自生成的District类代码

View Code
  1 代码

  2 

  3 [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="ExpressPlatformModel", Name="District")]

  4     [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]

  5     [global::System.Serializable()]

  6     public partial class District : global::System.Data.Objects.DataClasses.EntityObject

  7     {

  8         /// <summary>

  9         /// 创建新的 District 对象。

 10         /// </summary>

 11         /// <param name="districtID">DistrictID 的初始值。</param>

 12         /// <param name="cityID">CityID 的初始值。</param>

 13         /// <param name="districtName">DistrictName 的初始值。</param>

 14         public static District CreateDistrict(int districtID, int cityID, string districtName)

 15         {

 16             District district = new District();

 17             district.DistrictID = districtID;

 18             district.CityID = cityID;

 19             district.DistrictName = districtName;

 20             return district;

 21         }

 22         /// <summary>

 23         /// 架构中不存在属性 DistrictID 的注释。

 24         /// </summary>

 25         [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]

 26         [global::System.Runtime.Serialization.DataMemberAttribute()]

 27         public int DistrictID

 28         {

 29             get

 30             {

 31                 return this._DistrictID;

 32             }

 33             set

 34             {

 35                 this.OnDistrictIDChanging(value);

 36                 this.ReportPropertyChanging("DistrictID");

 37                 this._DistrictID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);

 38                 this.ReportPropertyChanged("DistrictID");

 39                 this.OnDistrictIDChanged();

 40             }

 41         }

 42         private int _DistrictID;

 43         partial void OnDistrictIDChanging(int value);

 44         partial void OnDistrictIDChanged();

 45         /// <summary>

 46         /// 架构中不存在属性 CityID 的注释。

 47         /// </summary>

 48         [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]

 49         [global::System.Runtime.Serialization.DataMemberAttribute()]

 50         public int CityID

 51         {

 52             get

 53             {

 54                 return this._CityID;

 55             }

 56             set

 57             {

 58                 this.OnCityIDChanging(value);

 59                 this.ReportPropertyChanging("CityID");

 60                 this._CityID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);

 61                 this.ReportPropertyChanged("CityID");

 62                 this.OnCityIDChanged();

 63             }

 64         }

 65         private int _CityID;

 66         partial void OnCityIDChanging(int value);

 67         partial void OnCityIDChanged();

 68         /// <summary>

 69         /// 架构中不存在属性 DistrictName 的注释。

 70         /// </summary>

 71         [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]

 72         [global::System.Runtime.Serialization.DataMemberAttribute()]

 73         public string DistrictName

 74         {

 75             get

 76             {

 77                 return this._DistrictName;

 78             }

 79             set

 80             {

 81                 this.OnDistrictNameChanging(value);

 82                 this.ReportPropertyChanging("DistrictName");

 83                 this._DistrictName = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);

 84                 this.ReportPropertyChanged("DistrictName");

 85                 this.OnDistrictNameChanged();

 86             }

 87         }

 88         private string _DistrictName;

 89         partial void OnDistrictNameChanging(string value);

 90         partial void OnDistrictNameChanged();

 91         /// <summary>

 92         /// 架构中不存在属性 PinYin 的注释。

 93         /// </summary>

 94         [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]

 95         [global::System.Runtime.Serialization.DataMemberAttribute()]

 96         public string PinYin

 97         {

 98             get

 99             {

100                 return this._PinYin;

101             }

102             set

103             {

104                 this.OnPinYinChanging(value);

105                 this.ReportPropertyChanging("PinYin");

106                 this._PinYin = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);

107                 this.ReportPropertyChanged("PinYin");

108                 this.OnPinYinChanged();

109             }

110         }

111         private string _PinYin;

112         partial void OnPinYinChanging(string value);

113         partial void OnPinYinChanged();

114         /// <summary>

115         /// 架构中不存在属性 PostalCode 的注释。

116         /// </summary>

117         [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]

118         [global::System.Runtime.Serialization.DataMemberAttribute()]

119         public string PostalCode

120         {

121             get

122             {

123                 return this._PostalCode;

124             }

125             set

126             {

127                 this.OnPostalCodeChanging(value);

128                 this.ReportPropertyChanging("PostalCode");

129                 this._PostalCode = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);

130                 this.ReportPropertyChanged("PostalCode");

131                 this.OnPostalCodeChanged();

132             }

133         }

134         private string _PostalCode;

135         partial void OnPostalCodeChanging(string value);

136         partial void OnPostalCodeChanged();

137     }


这是我手写的District类

View Code
 1 代码

 2 

 3   [DataContract]

 4         [Serializable]

 5         public class SDistrict

 6         {

 7             public SDistrict() { }

 8             [DataMember]

 9             private int districtID = 0;

10 

11             public int DistrictID

12             {

13                 get { return districtID; }

14                 set { districtID = value; }

15             }

16             [DataMember]

17             private int cityID = 0;

18 

19             public int CityID

20             {

21                 get { return cityID; }

22                 set { cityID = value; }

23             }

24             [DataMember]

25             private string districtName = string.Empty;

26 

27             public string DistrictName

28             {

29                 get { return districtName; }

30                 set { districtName = value; }

31             }

32             [DataMember]

33             private string pinYin = string.Empty;

34 

35             public string PinYin

36             {

37                 get { return pinYin; }

38                 set { pinYin = value; }

39             }

40             [DataMember]

41             private string postalCode = string.Empty;

42 

43             public string PostalCode

44             {

45                 get { return postalCode; }

46                 set { postalCode = value; }

47             }

48 

49         }


大家都看见了,edmx生成的和手写的District结构都是一模一样的,同样都有DataContract这个类属性,可以序列化和反序列化.下面是我Service中返回不同实体集合的一段代码,

自定义District类获取方法

View Code
 1 代码

 2 

 3   public List<SDistrict> initBuffByDistrict() //自己手写的实体类

 4         {

 5             

 6             using (ExpressPlatformEntities db = new ExpressPlatformEntities())

 7             {

 8 

 9                 List<District> result = db.District.ToList<District>();

10                 List<SDistrict> result1 = new List<SDistrict>(result.Count);

11                 for (int i = 0; i < result.Count; i++)

12                 {

13                     SDistrict sd = new SDistrict();

14                     sd.DistrictID = result[i].DistrictID;

15                     sd.DistrictName = result[i].DistrictName;

16                     sd.CityID = result[i].CityID;

17                     sd.PinYin = result[i].PinYin;

18                     sd.PostalCode = result[i].PostalCode;

19                     result1.Add(sd);

20                 }

21               

22                

23                

24                 return result1;

25             }

edmx生成的District类获取方法

View Code
1 代码

2 

3         public List<District> GetDistrictList()

4         {

5             using (ExpressPlatformEntities db = new ExpressPlatformEntities())

6             {

7                 return db.District.ToList();

8             }

9         }


 

客户端使用http协议调用这两个方法的结果我用Fiddler测试工具抓取响应的消息所获得才恍 然大悟啊,请看下面

测试返回省市区表对象3304,以下是用entity framework 自生成的实体集合

==================================================================

Request Count: 1 //请求数

Bytes Sent: 1,090//发送字节数

Bytes Received: 2,462,366 //接收字节数

 

ACTUAL PERFORMANCE

--------------

Requests started at:10:24:09:1406 //请求开始

Responses completed at:10:24:17:5781 //响应返回

Aggregate Session time:00:00:08:4375 //耗时

Sequence (clock) time:00:00:08.4375000 //总耗时

 

 

测试返回省市区表对象3304,以下是用手写的实体集合

===============================================

Request Count: 1//请求数

Bytes Sent: 1,088//发送字节

Bytes Received: 634,171//接收字节

 

ACTUAL PERFORMANCE

--------------

Requests started at:10:16:07:2500//请求开始

Responses completed at:10:16:09:5625//响应返回

Aggregate Session time:00:00:02:3125//耗时

Sequence (clock) time:00:00:02.3125000//总耗时

 

 

===================华丽的分割线========================================

 

相差了6秒多,而且字节数相差了4倍左右,3304个实体的数据总量一共是600K左右,传600K数据需要8秒?

 

我把这两个集合序列化到文本一看,一个edmx生成的实体类集合有2.33MB的容量,手写的实体集合只有610K,实际上手写的

 

实体集合序列化为Soap-XML进行传输的时候那些声明数据的类型的XML节点只占用了10K的大小,而通过edmx生成的

 

Soap-XML包含了edmx的许多属性,这样就能得出为什么手写的比生成的快了.

 

文章到这里结束了,希望能给大家提供帮助,也欢迎大牛和同行拍砖指点和纠正

你可能感兴趣的:(framework)