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的许多属性,这样就能得出为什么手写的比生成的快了.

 

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

posted on 2012-12-16 02:06  davidkam  阅读(443)  评论(0编辑  收藏  举报