RavenDB中作为Id的Guid

RavenDB中作为Id的Guid,ravendb,Ravendb,各国: 支持数字或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; } } 然

各国:

支持数字或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; }
}
然后,我创建了以下投影:

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
}
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
            };
    }
}
我创建了以下索引以创建投影:

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
}
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
            };
    }
}
类MyIndex:AbstractIndexCreationTask
{
公共索引()
{
Map=docs=>
从文档中的d开始
选择新的
{
d、 身份证,
d、 投标,
BName=string.Empty
};
TransformResults=(数据库、结果)=>
从r到结果
设b=database.Load(“bs/”+r.BId.ToString())
选择新的
{
r、 身份证,
r、 投标,
BName=b.名称
};
}
}
当我使用以下查询时:

session.Query<AB, MyIndex>().FirstOrDefault(t => t.Id == guid);
session.Query().FirstOrDefault(t=>t.Id==guid);
我得到一个例外:

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

问题:

  • 这是由我的投影中的转换引起的,因为
    Id
    是一个字符串,不再是我的Guid。但是,省略它不会返回Id。我必须做什么

  • 我必须使用字符串building
    “bs/”+r.BId.ToString()
    来加载相关文档。有没有办法不必这样做?是否有某种函数可以为我解析doc标签

  • 有没有一种通用的方法可以完全去掉文档标签

  • 我的约束。

    我将生成Guid,不能让RavenDb为我生成它。我知道文档ID实际上是字符串,但我确实需要使用我创建的Guid。我更愿意拥有我的实体的
    Id
    属性


    我正在使用Raven.Client 1.0.972

    您可以在保存时向RavenDB显式提供ID:

    session.Store(doc, explicitIdValueString);
    

    explicitIdValueString
    可以是Guid字符串。此值将用于标识整个数据库中的文档,并且不会以类型标记名作为前缀。您还可以通过覆盖
    IDocumentStore.conventions
    上的约定(如
    FindTypeTagName
    Func

    )来定制标记名或ID生成策略,主要问题是RavenDB可以在客户端处理数字/整数,但在服务器端,RavenDB使用字符串ID


    通常,不建议使用GUID/数字ID

    您可以使用MultiMap/Reduce索引来实现这一点,但您需要一些技巧:

    1) 您需要减少使用字符串,而不是guid。您仍然可以在AB类中以GUI的形式获取这些值,我将在下面演示

    2) 您不能调用AB类的第一个属性“Id”,因为raven将尝试将其转换为“文档Id”。所以称它为“援助”,它会很好地工作

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

    下面是一个示例程序,它将所有内容放在一起。这表明它确实有效,但我认为它也说明了为什么Ayende更喜欢字符串标识符,这样就不必处理这种混乱

    使用系统;
    使用System.Linq;
    使用Raven.Client.Document;
    使用Raven.Client.index;
    名称空间ravenscartest
    {
    班级计划
    {
    静态void Main()
    {
    var documentStore=new documentStore{Url=”http://localhost:8080" };
    初始化();
    CreateIndexes(typeof(Program).Assembly,documentStore);
    使用(var session=documentStore.OpenSession())
    {
    var b=new b{Id=Guid.NewGuid(),Name=“Foo”};
    var a=newa{Id=Guid.NewGuid(),BId=b.Id};
    会议.商店(a);
    会议.商店(b);
    session.SaveChanges();
    }
    使用(var session=documentStore.OpenSession())
    {
    var a=session.Query().Customize(x=>x.WaitForNonSaleResults()).First();
    var b=session.Query().Customize(x=>x.WaitForNonSaleResults()).First();
    WriteLine(“A:Id={0}”,A.Id);
    WriteLine(“BId={0}”,a.BId);
    Console.WriteLine();
    WriteLine(“B:Id={0}”,B.Id);
    WriteLine(“Name={0}”,b.Name);
    Console.WriteLine();
    var guid=a.Id;
    var ab=session.Query().Customize(x=>x.WaitForNonSaleResults())
    .FirstOrDefault(t=>t.AId==guid);
    if(ab==null)
    控制台写入线(“AB:NULL”);
    其他的
    {
    WriteLine(“AB:AId={0}”,AB.AId);
    Console.WriteLine(“BId={0}”,ab.BId);
    WriteLine(“BName={0}”,ab.BName);
    Console.WriteLine();
    }
    }
    Console.WriteLine();
    控制台。WriteLine(“完成”);
    Console.ReadLine();
    }
    }
    甲级
    {
    公共Guid Id{get;set;}
    公共Guid BId{get;set;}
    }
    B类
    {
    公共Guid Id{get;set;}
    公共字符串名称{get;set;}
    }
    AB类
    {
    公共Guid辅助{get;set;}
    公共Guid BId{get;set;}
    公共字符串BName{get;set;}
    }
    类MyIndex:AbstractMultiMapIndexCreationTask
    {
    公共索引()
    {
    AddMap(文档=>来自文档中的
    选择新的
    {
    AId=a.Id.ToString().Split('/')[1],
    a、 投标,
    BName=(字符串)null
    });
    AddMap(文档=>来自文档中的b
    选择新的
    {
    AId=(字符串)null,
    BId=b.Id.ToString().Split('/')[1],
    BName=b.名称
    });
    还原
    
    public class User
    {
        public User(Guid? guid = null)
        {
            IdPart = (guid ?? Guid.NewGuid()).ToString("N")
        }
    
        string IdPart { get; }
        string Id => $"Users/{IdPart}"
    
    public class Project
    {
        public User(Guid? userId = null)
        {
            UserId = "Users/" + (guid ?? Guid.NewGuid()).ToString("N");
            Id = $"{UserId}/project/"
    
        }