如何让RavenDB与WCF数据服务一起工作?

如何让RavenDB与WCF数据服务一起工作?,wcf,wcf-data-services,ravendb,odata,Wcf,Wcf Data Services,Ravendb,Odata,我使用WCF数据服务5.3.0和反射数据提供程序。我的源数据存储在RavenDB中,因此我的所有查询都被延迟。所以,在应用OData筛选器之后,在结果返回到客户端之前,是否有一些方法可以为我的查询调用.ToList() 更新:我的数据模型属性声明 public IQueryable<PositionModel> Positions { get { using (var session = OLAPDocument

我使用WCF数据服务5.3.0和反射数据提供程序。我的源数据存储在RavenDB中,因此我的所有查询都被延迟。所以,在应用OData筛选器之后,在结果返回到客户端之前,是否有一些方法可以为我的查询调用.ToList()

更新:我的数据模型属性声明

    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();
            }
        }
    }

好的,我必须去刷新我关于WCF数据服务工作原理的记忆。肖恩·维尔德茅斯有

主要问题是您试图使用
Select
语句转换查询客户端。当您返回一个
IQueryable
时,它应该直接连接到linq提供程序——在本例中,是RavenDB查询的输出。您可以应用
Where
OrderBy
过滤器,但不能使用
Select
语句进行投影。这打破了查询链

因此,如果要从数据库中的
ConsolidatedApplicationPosition
对象投影到要返回到WCF数据服务的
PositionModel
对象,则必须以另一种方式进行。以下是一些选项:

  • 如果需要投影的所有字段都已在源数据中,则可以执行以下操作:

    return session.Query<ConsolidatedApplicationPosition>()
                  .AsProjection<PositionModel>();
    
    或者通过使用
    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 ...
    
         };
      }
    }
    
    公共类YourIndex:AbstractIndexCreationTask
    {
    公共索引()
    {
    Map=docs=>
    从文档中的文档
    选择新的
    {
    //您需要映射可能查询的任何字段
    //或者通过odata过滤器进行排序。
    };
    TransformResults=(数据库、文档)=>
    从文档中的文档
    选择新的位置模型
    {
    //如果结果中需要整数标识符,
    //您必须将它们从文档密钥中拆分,如下所示:
    ID=int.Parse(doc.ID.ToString().Split('/')[1]),
    //否则,只需执行以下操作:
    ID=文件ID,
    //把你所有的其他领域也带过来
    平台=文件平台
    等
    };
    }
    }
    
    索引就位后,将按如下方式进行查询:

    return session.Query<PositionModel, YourIndex>();
    
    返回session.Query();
    

  • 使用任一选项,查询中都没有select语句,因此无需执行
    ToList
    AsQueryable
    。您只需将RavenDB linq提供程序的
    IQueryable
    接口发送到WCF数据服务上下文中即可。

    OData需要一个
    IQueryable
    ,这是设计延迟的。如果您想要更具体的答案,请显示一些代码。使用一些源代码更新了问题。
    .AsQueryable()
    在这里是多余的。你可以不说了。你的问题还有其他方面吗?我不知道你想做什么。什么不起作用?当前代码总是生成空列表,直到我调用.ToList()。同样值得注意的是,他们正在为RavenDB 2.5(尚未发布)将转换与索引分离。这将允许您对动态索引进行转换,而不必创建静态索引。谢谢玩具的回复。它非常有用。但是我的问题是不同的(更新的假设)@JiříGluškov-我读了你的更新,但那不是真的。一个空的lucene查询返回所有的数据。这非常简单,我是用Fiddler发现的。我还发现,在对RavenDB服务器的请求中,如果查询参数不为空,则响应是正确的。@JiříGluškov-仔细阅读我的答案。这是因为您正在执行的
    Select
    操作中断了查询。
    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>();