我将WCF Data Services 5.3.0与Reflection Data Provider一起使用。我的源数据存储在RavenDB中,所以我的所有查询都是延迟的。那么,在应用OData过滤器之后和结果返回给客户端之前,是否有一些方法可以为我的查询调用.ToList()?
更新:我的DataModel属性声明
public IQueryable<PositionModel> Positions
{
get
{
using (var session = OLAPDocumentStore.OpenSession())
{
return session
.Query<ConsolidatedApplicationPosition>()
.Select(x => new PositionModel
{
ApplicationId = x.ApplicationId,
CategoryId = x.CategoryId,
ID = x.Id,
Platform = x.Platform,
Position = x.Position,
RegionalCode = x.RegionalCode,
Timestamp = x.Timestamp,
TopListId = x.TopListId
})
.AsQueryable();
}
}
}
解决方案请参阅@ matt-johnson回答,不要忘记将[DataMember]添加到模型中的所有属性
[DataContract, DataServiceKey("Id")]
public class PositionModel
{
[DataMember]
public string Id { get; set; }
[DataMember]
public string ApplicationId { get; set; }
[DataMember]
public string CategoryId { get; set; }
[DataMember]
public int Position { get; set; }
[DataMember]
public string RegionalCode { get; set; }
[DataMember]
public DateTime Timestamp { get; set; }
[DataMember]
public string TopListId { get; set; }
}
答案 0 :(得分:2)
好的,我不得不重温我对WCF数据服务如何工作的记忆。 Shawn Wildermuth有an excellent example video。
主要问题是您尝试使用Select
语句转换查询客户端。当你返回IQueryable
时,它应该直接挂钩到linq提供程序 - 在这种情况下,是RavenDB查询的输出。您可以应用Where
和OrderBy
过滤器,但不能使用Select
语句进行投影。这打破了查询链。
因此,如果您想要从数据库中的ConsolidatedApplicationPosition
对象投射到要返回到WCF数据服务的PositionModel
对象,那么您将不得不以另一种方式进行投影。以下是一些选项:
如果您需要投影的所有字段都已包含在源数据中,那么您可以这样做:
return session.Query<ConsolidatedApplicationPosition>()
.AsProjection<PositionModel>();
这里唯一的问题是您的标识符不匹配。 Raven的默认标识符约定是Id
(Pascal case),而WCF是ID
(大写)。您可以通过更改Raven的约定来排列它们:
DocumentStore.Conventions.FindIdentityProperty = x => x.Name == "ID";
或通过使用DataServiceKey
属性更改WCF的约定:
[DataContract, DataServiceKey("Id")]
public class PositionModel
{
[DataMember]
public int Id { get; set; }
...
}
如果要保持标识符不匹配,或者如果要转换更多字段,则无法使用动态索引。相反,您必须创建静态索引并使用变换来控制投影:
public class YourIndex : AbstractIndexCreationTask<ConsolidatedApplicationPosition>
{
public YourIndex()
{
Map = docs =>
from doc in docs
select new
{
// You need to map any fields that you might query
// or sort on through the odata filters.
};
TransformResults = (database, docs) =>
from doc in docs
select new PositionModel
{
// if you need integer identifiers in your result,
// you'll have to split them from the doc key, like this:
ID = int.Parse(doc.Id.ToString().Split('/')[1]),
// otherwise, just do this:
ID = doc.Id,
// bring over all of your other fields as well
Platform = doc.Platform
... etc ...
};
}
}
在索引到位后,您可以这样查询:
return session.Query<PositionModel, YourIndex>();
使用任一选项,查询中都没有select语句,因此无需执行ToList
或AsQueryable
。您只是将RavenDB linq提供程序的IQueryable
接口发送到WCF数据服务上下文。