该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'.
问题:
它是由我的投影中的转换引起的,因为它Id是一个字符串而不是我的Guid.但是,将其删除将不会返回Id.我必须做什么?
我必须使用字符串构建"bs/" + r.BId.ToString()来加载相关的文档.有没有办法不必这样做?是否有某种功能可以为我解析doc标签?
是否有一种通用的方法来完全删除文档标记?
我的约束.
我将生成Guid并且不能让RavenDb为我生成它.我知道文档ID实际上是字符串,但我真的需要使用我创建的Guid.我更愿意拥有Id我的实体的财产.
我正在使用Raven.Client 1.0.972
你可以使用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)