在RavenDB中作为Id的Guid

Mik*_*erg 6 ravendb

RavenDb文档状态:

支持Numeric或Guid Id属性,可以无缝工作.在这种情况下,RavenDB将自动使内部字符串ID与实体中显示的数字或Guid值之间进行转换.

我存储了以下对象:

class A
{
    public Guid Id { get; set; }
    public Guid BId { get; set; }
}

class B
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建了以下投影:

class AB
{
    public Guid Id { get; set; }       // This should be the Id of A
    public Guid BId { get; set; }      // This should be the Id of B
    public string BName { get; set; }  // This should be the name of B
}
Run Code Online (Sandbox Code Playgroud)

我创建了以下索引来创建投影:

class MyIndex : AbstractIndexCreationTask<AB>
{
    public MyIndex()
    {
        Map = docs =>
            from d in docs
            select new
            {
                d.Id,
                d.BId,
                BName = string.Empty
            };

        TransformResults = (database, results) =>
            from r in results
            let b = database.Load<B>("bs/" + r.BId.ToString())
            select new
            {
                r.Id,
                r.BId,
                BName = b.Name
            };
    }
}
Run Code Online (Sandbox Code Playgroud)

当我使用以下查询时:

session.Query<AB, MyIndex>().FirstOrDefault(t => t.Id == guid);
Run Code Online (Sandbox Code Playgroud)

我得到这个例外:

将值"bs/cc0a65ae-dd36-4437-8a57-fa20b91eeef7"转换为"System.Guid"类型时出错.路径'Id'.

问题:

  1. 它是由我的投影中的转换引起的,因为它Id是一个字符串而不是我的Guid.但是,将其删除将不会返回Id.我必须做什么?

  2. 我必须使用字符串构建"bs/" + r.BId.ToString()来加载相关的文档.有没有办法不必这样做?是否有某种功能可以为我解析doc标签?

  3. 是否有一种通用的方法来完全删除文档标记?

我的约束.

我将生成Guid并且不能让RavenDb为我生成它.我知道文档ID实际上是字符串,但我真的需要使用我创建的Guid.我更愿意拥有Id我的实体的财产.

我正在使用Raven.Client 1.0.972

Mat*_*int 6

你可以使用MultiMap/Reduce Index实现这个目标,但是你需要一些hackery:

1)你需要减少使用字符串,而不是guids.您仍然可以在AB类中将这些值作为guid返回,我将在下面演示.

2)你不能调用你的AB类"Id"的第一个属性,因为raven会尝试将其翻译为"__document_id".所以称之为"AId",它会正常工作.

3)在映射阶段,您必须自己操纵字符串以去除文档密钥前缀.

这是一个将所有内容组合在一起的示例程序.这表明它确实有效,但我认为它也说明了为什么Ayende更喜欢字符串标识符,所以你不必处理这种混乱.

using System;
using System.Linq;
using Raven.Client.Document;
using Raven.Client.Indexes;

namespace RavenScratchTest
{
  class Program
  {
    static void Main()
    {
      var documentStore = new DocumentStore { Url = "http://localhost:8080" };
      documentStore.Initialize();
      IndexCreation.CreateIndexes(typeof(Program).Assembly, documentStore);

      using (var session = documentStore.OpenSession())
      {
        var b = new B { Id = Guid.NewGuid(), Name = "Foo" };
        var a = new A { Id = Guid.NewGuid(), BId = b.Id };

        session.Store(a);
        session.Store(b);

        session.SaveChanges();
      }

      using (var session = documentStore.OpenSession())
      {
        var a = session.Query<A>().Customize(x => x.WaitForNonStaleResults()).First();
        var b = session.Query<B>().Customize(x => x.WaitForNonStaleResults()).First();

        Console.WriteLine("A:  Id = {0}", a.Id);
        Console.WriteLine("   BId = {0}", a.BId);
        Console.WriteLine();
        Console.WriteLine("B:  Id = {0}", b.Id);
        Console.WriteLine("  Name = {0}", b.Name);
        Console.WriteLine();

        var guid = a.Id;
        var ab = session.Query<AB, MyIndex>().Customize(x => x.WaitForNonStaleResults())
          .FirstOrDefault(t => t.AId == guid);

        if (ab == null)
          Console.WriteLine("AB: NULL");
        else
        {
          Console.WriteLine("AB:  AId = {0}", ab.AId);
          Console.WriteLine("   BId = {0}", ab.BId);
          Console.WriteLine("   BName = {0}", ab.BName);
          Console.WriteLine();
        }
      }

      Console.WriteLine();
      Console.WriteLine("Done.");
      Console.ReadLine();
    }
  }

  class A
  {
    public Guid Id { get; set; }
    public Guid BId { get; set; }
  }

  class B
  {
    public Guid Id { get; set; }
    public string Name { get; set; }
  }

  class AB
  {
    public Guid AId { get; set; }
    public Guid BId { get; set; }
    public string BName { get; set; }
  }

  class MyIndex : AbstractMultiMapIndexCreationTask<MyIndex.ReduceResult>
  {
    public MyIndex()
    {
      AddMap<A>(docs => from a in docs
                select new
                {
                  AId = a.Id.ToString().Split('/')[1],
                  a.BId,
                  BName = (string)null
                });

      AddMap<B>(docs => from b in docs
                select new
                {
                  AId = (string)null,
                  BId = b.Id.ToString().Split('/')[1],
                  BName = b.Name
                });

      Reduce = results => from result in results
                group result by result.BId
                into g
                select new
                  {
                    g.FirstOrDefault(x => x.AId != null).AId,
                    BId = g.Key,
                    g.FirstOrDefault(x => x.BName != null).BName
                  };
    }

    internal class ReduceResult
    {
      public string AId { get; set; }
      public string BId { get; set; }
      public string BName { get; set; }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这是在2012年编写的.在较新版本的RavenDB中,您应该使用[`LoadDocument`](http://ravendb.net/docs/2.5/client-api/querying/static-indexes/indexing-related-documents而不是multimap/reduce. (2认同)