如何让RavenDB与WCF数据服务一起使用?

时间:2013-02-28 14:38:27

标签: wcf wcf-data-services ravendb odata

我将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; }
}

1 个答案:

答案 0 :(得分:2)

好的,我不得不重温我对WCF数据服务如何工作的记忆。 Shawn Wildermuth有an excellent example video

主要问题是您尝试使用Select语句转换查询客户端。当你返回IQueryable时,它应该直接挂钩到linq提供程序 - 在这种情况下,是RavenDB查询的输出。您可以应用WhereOrderBy过滤器,但不能使用Select语句进行投影。这打破了查询链。

因此,如果您想要从数据库中的ConsolidatedApplicationPosition对象投射到要返回到WCF数据服务的PositionModel对象,那么您将不得不以另一种方式进行投影。以下是一些选项:

  1. 如果您需要投影的所有字段都已包含在源数据中,那么您可以这样做:

    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; }
    
        ...
    }
    
  2. 如果要保持标识符不匹配,或者如果要转换更多字段,则无法使用动态索引。相反,您必须创建静态索引并使用变换来控制投影:

    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>();
    
  3. 使用任一选项,查询中都没有select语句,因此无需执行ToListAsQueryable。您只是将RavenDB linq提供程序的IQueryable接口发送到WCF数据服务上下文。

相关问题