Silverlight + WCF + EF4 调用出错,Server 端的Exception:The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
Server 端的代码如下:
public IEnumerable<WTTResultInfo> GetOfficialWTTResult(int page_index, int page_count) { using (PETTestDBEntities db = new PETTestDBEntities()) { return db.WTTResultInfoes.OrderByDescending(e => e.StartTime) .Where(e => e.IsOfficial == true) .Skip(page_index * page_count) .Take(page_count) .ToArray(); } }
数据库表结构 (.edmx 文件):
可以看到这里有一个Navigation Property:WTTResult。对应的 .Designer.cs 部分代码:
/// <summary> /// No Metadata Documentation available. /// </summary> [XmlIgnoreAttribute()] [SoapIgnoreAttribute()] [DataMemberAttribute()] [EdmRelationshipNavigationPropertyAttribute("PETTestDBModel", "FK_ResultData_WTTResult", "WTTResult")] public WTTResult WTTResult { get { return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<WTTResult>("PETTestDBModel.FK_ResultData_WTTResult", "WTTResult").Value; } set { ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<WTTResult>("PETTestDBModel.FK_ResultData_WTTResult", "WTTResult").Value = value; } }
在 Client 端 (Silverlight)中调用Services时,出现错误,Debug时发现 Exception 如图:
主要是因为在代码中使用了 using (PETTestDBEntities db = new PETTestDBEntities()), 导致数据在返回之前就被Close了。如果去掉using,就没有问题了。但这个不是解决问题的根本办法。在研究过程中,试图删除DataMemberAttribute,这样就不会在WSDL中出现这个Property,果然可以Pass。也就是说,因为在Serialize这个Property时有问题。但这个Property不是我需要的。怎么可以在WCF通讯中去掉它呢?这里的SoapIgnoreAttribute并没有作用。搜了一下发现,在ObjectContext下有一个ContextOptions.LazyLoadingEnabled,默认是True,导致在传输时会得到所有的Properties。如果设置成False,就不会传输Navigation Property。修改后的代码如下:
using (PETTestDBEntities db = new PETTestDBEntities()) { db.ContextOptions.LazyLoadingEnabled = false; // .... }
再次运行,Pass。Debug时可以看到,WTTResult == null。其实,如果我们一开始就不需要LazyLoading模式的话,可以在Design石图中设置。打开.edmx文件,鼠标点击空白处,查看属性, 如图: