如何加载<;T>;不使用默认ID生成策略时,受集合约束的RavenDB文档
在Ravendb4(v4.0.3-patch-40031)中,我有两种文档类型:如何加载<;T>;不使用默认ID生成策略时,受集合约束的RavenDB文档,ravendb,ravendb4,Ravendb,Ravendb4,在Ravendb4(v4.0.3-patch-40031)中,我有两种文档类型:Apple和Orange。两者具有相似但又截然不同的特性。我在运行时的代码中遇到了一个bug,有时候会提供一个苹果的ID,但会返回一个橙色。吓人 深入研究一下,这有点道理。但我正在努力寻找一个合适的解决方案 来吧。在RavenDB中,我将一个Apple存储为文档: id: "078ff39b-da50-4405-9615-86b0d185ba17" { "Name": "Elstar", "@meta
Apple
和Orange
。两者具有相似但又截然不同的特性。我在运行时的代码中遇到了一个bug,有时候会提供一个苹果的ID,但会返回一个橙色。吓人
深入研究一下,这有点道理。但我正在努力寻找一个合适的解决方案
来吧。在RavenDB中,我将一个Apple
存储为文档:
id: "078ff39b-da50-4405-9615-86b0d185ba17"
{
"Name": "Elstar",
"@metadata": {
"@collection": "Apples",
"Raven-Clr-Type": "FruitTest.Apple, FruitTest"
}
}
在本例中,假设数据库中没有存储Orange
文档。我希望这次测试能够成功:
//排列-使用Orange集合中不存在的苹果ID
变量id_of_apple=“078ff39b-da50-4405-9615-86b0d185ba17”;
//装一个橘子
var target=wait_session.LoadAsync(“078ff39b-da50-4405-9615-86b0d185ba17”);
//assert-应该为null,因为没有带有该Id的橙色
target.Should().BeNull(因为:“提供的ID不是桔子而是苹果”);
。。。但它失败了。发生的情况是文档ID存在,因此RavenDB加载文档。不管它是什么类型的。它尝试自动映射属性。我预期或错误地假设加载类型说明符会将查找限制到该特定文档集合。相反,它在整个数据库中获取+映射,而不是将其限制为类型
。因此,该行为不同于.Query
,后者对集合没有约束
需要注意的是,通过将Id设置为string.Empty
(符合),我使用guid作为身份策略。我假设默认的ID策略,如entityname/1001
,不会有这个问题
但他们并没有真正提到这是否是故意的。它只说:“从数据库下载文档并将其转换为实体。”
但是,出于某些原因,我确实希望将加载操作约束到单个集合。或者,更好的说法是,尽可能高效地从特定集合按ID加载文档。如果它不存在,则返回null
好了,有两种方法可以实现这一点:
.Query.Where(x=>x.Id==Id)
,而不是.Load(Id)
.Load(id)
,然后检查(~不知何故,请参见底部)它是否是集合T的一部分公共异步任务获取(字符串id)
{
var instance=wait_session.LoadAsync(id);
if(instance==null)返回null;
//收集的“不知何故”检查
var expectedTypeName=string.Concat(typeof(T).Name,“s”);
var actualTypeName=_session.Advanced.GetMetadataFor(实例)[Constants.Documents.Metadata.Collection].ToString();
如果(实际类型名称!=预期类型名称)
{
//边缘盒:苹果!=橙色
返回null;
}
返回实例;
}
如何繁殖
更新2018/04/19-在有用的评论后添加了此可复制样品(谢谢)
型号
公共接口IFruit
{
字符串Id{get;set;}
字符串名称{get;set;}
}
公共级苹果:IFruit
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
公共级橙色:IFruit
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
测试例如,在同一个会话中抛出InvalidCastException(有效),但在第二个会话中则不起作用
公共类UnitTest1
{
[事实]
公共异步任务SameSession_Works_和_Throws_InvalidCastException()
{
var store=new DocumentStore()
{
URL=new[]{”http://192.168.99.100:32772"},
数据库=“水果”
}.Initialize();
使用(var session=store.OpenAsyncSession())
{
新苹果
{
Id=Guid.NewGuid().ToString(),
Name=“Elstar”
};
wait session.StoreAsync(苹果);
wait session.saveChangesSync();
等待Assert.ThrowsAsync(()=>session.LoadAsync(apple.Id));
}
}
[事实]
公共异步任务不同会话失败()
{
var store=new DocumentStore()
{
URL=new[]{”http://192.168.99.100:32772"},
数据库=“水果”
}.Initialize();
使用(var session=store.OpenAsyncSession())
{
var appleId=“ca5d9fd0-475b-41de-a1ab-57bb1e3ce018”;
//这个应该坏了,因为…它是个苹果
//…但它没有-它返回一个橙色
var orange=await session.LoadAsync(appleId);
等待Assert.ThrowsAsync(()=>session.LoadAsync(appleId));
}
}
}
.Query.Where(x=>x.Id==Id)
是一种方法。在Ravendb4.0中,按ID进行的查询直接由封面下的文档存储(而不是索引)处理,因此它的效率与Load
相同
您的场景的优点是查询的范围仅限于指定的集合。好吧,我发现了问题所在,但我