如何在WCF数据服务的服务端执行连接操作
我知道“连接”在客户端不支持WCF DS,这就是为什么我决定在服务器端添加一个方法来执行“连接”并返回结果作为自定义类型对象。 服务看起来是这样的:如何在WCF数据服务的服务端执行连接操作
public class CWcfDataService : DataService<CEntities>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
config.UseVerboseErrors = true;
config.RegisterKnownType(typeof(CASE_STAGE_HISTORY_EXTENDED));
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
[WebGet]
public IQueryable<CASE_STAGE_HISTORY_EXTENDED> GetCASE_STAGE_HISTORY_EXTENDEDByDocId(int docId)
{
CEntities context = new CEntities();
return (from c in context.CASE_STAGE_HISTORY
join a in context.USRs on c.CREATOR_ID equals a.USRID
select new CASE_STAGE_HISTORY_EXTENDED()
{
CASE_STAGE_ID = c.CASE_STAGE_HISTORY_ID,
CASE_STAGE_NAME = c.CASE_STAGE_NAME,
CREATE_DATE = c.CREATE_DATE,
CREATOR_ID = c.CREATOR_ID,
DOC_ID = c.DOC_ID,
LAST_VARIANT_DOCUMENT_ID = c.LAST_VARIANT_DOCUEMENT_ID,
CREATOR_FULLNAME = a.FULLNAME
});
}
}
和定制类:
[DataServiceKey("CASE_STAGE_ID")]
public class CASE_STAGE_HISTORY_EXTENDED
{
public int CASE_STAGE_ID { get; set; }
public int DOC_ID { get; set; }
public string CASE_STAGE_NAME { get; set; }
public int? LAST_VARIANT_DOCUMENT_ID { get; set; }
public DateTime? CREATE_DATE { get; set; }
public int? CREATOR_ID { get; set; }
public string CREATOR_FULLNAME { get; set; }
}
当我尝试更新Visual Studio的服务参考我不断得到错误:
如果我删除public IQueryable<CASE_STAGE_HISTORY_EXTENDED> GetCASE_STAGE_HISTORY_EXTENDEDByDocId(int docId)
部分 - 更新服务参考我得到另一个错误:
The server encountered an error processing the request. The exception message is 'Internal Server Error. The type 'CourtWcf.Code.CASE_STAGE_HISTORY_EXTENDED' is not a complex type or an entity type.'.
环境:Visual Studio 2010中,.NET 4
添加了外键并实现了LoadProperty。请参阅我采用此解决方案的文章:http://thedatafarm.com/blog/data-access/the-cost-of-eager-loading-in-entity-framework/ 仍然如果我在数据库中没有关系(例如,我没有外键) - 我有另一种解决方案:创建存储过程并将其与数据库模型中的导入进行映射。之后,创建复杂类型,也可以在客户端工作(你必须通过URI访问它,而不是使用lambda扩展)。见示例here。
非常感谢在这个主题中的其他回答者,您让我更深入了解这个主题。
对于初学者来说,WCF不支持IQueryable的。那就是你的问题。
在你的情况IEnumerable应该工作。
你应该将服务看作是具有方法并返回“数据”的东西。这些数据可以是单个值,对象实例或对象集合。客户不应该考虑调用服务来进行连接,而应该“给我这些和那些数据 - 给定这些参数”。
您的方法名赋予正确的“intent”GetCaseStageHistoryExtendedByDocId(int docId),并且您返回的是CASE_STAGE_HISTORY_EXTENDED对象的集合。而已。
IQueryable意味着完全不同的东西,这个概念不属于服务本身。
编辑
尝试通过调用就可以了ToList()方法,将您的可查询到列表中。
返回(从C中context.CASE_STAGE_HISTORY 加入在上c.CREATOR_ID context.USRs等于a.USRID 选择新CASE_STAGE_HISTORY_EXTENDED() { CASE_STAGE_ID = c.CASE_STAGE_HISTORY_ID, CASE_STAGE_NAME = c.CASE_STAGE_NAME, 。CREATE_DATE = c.CREATE_DATE, CREATOR_ID = c.CREATOR_ID, DOC_ID = c.DOC_ID, LAST_VARIANT_DOCUMENT_ID = c.LAST_VARIANT_DOCUEMENT_ID, CREATOR_FULLNAME = a.FULLNAME })ToList();
请注意,您只能将可序列化对象发送到客户端。所以首先确保你的对象是可序列化的。
我假设数据服务基于实体框架模型(CEntities类是一个ObjectContext)。 如果是这种情况,则类型完全从EF模型(CSDL)中读取,而类定义或多或少被忽略。所以你需要在EF模型中定义服务操作返回的类型。还要注意,为了让IQueryable工作,该类型必须被EF识别为实体类型(这可能需要映射到数据库,或者EF专家会知道更多)。
异常消息是'无法加载方法'System.Collections.Generic.IEnumerable'1 [CWcf.Code。')的'返回类型的元数据'System.Collections.Generic.IEnumerable'1 [CWcf.Code.CASE_STAGE_HISTORY_EXTENDED]'。 CASE_STAGE_HISTORY_EXTENDED] GetCASE_STAGE_HISTORY_EXTENDEDByDocId(Int32)'。'。 – 0x49D1 2011-02-24 10:06:43
你的类型是可串行化的吗?你测试过它是可序列化的吗? – 2011-02-24 10:16:53
@nihi_l_ist,尝试在返回之前通过调用ToList()方法将查询转换为“List”。 – 2011-02-24 10:22:55