使用反射类型查询RavenDB

时间:2013-11-07 14:55:35

标签: c# ravendb

我通过反射动态加载类型,实例化类,用数据填充它们然后将它们保存到RavenDB。它们都实现了接口IEntity

在RavenDB UI中,我可以看到正确显示的类,并且元数据具有正确的CLR类型。

现在我想要恢复数据,更改它然后保存它。

我想做什么

我有System.Type与RavenDB的CLR元数据中的实体相匹配,假设它被称为myType,我想这样做:

session.Query(myType).ToList(); // session is IDocumentSession

但是你不能这样做,因为RavenDB会像这样查询:

session.Query<T>();

我在编译时没有通用类型T,我正在动态加载。

解决方案1 ​​ - 大文档

我尝试的第一种方法(用于概念验证)是将所有实体包装在单个数据对象中并保存:

public class Data {
    List<IEntity> Entities = new List<IEntity>();
}

假设会话正确打开/关闭,并且我有一个id:

var myDataObject = session.Load<Data>(Id);

myDataObject.Entities.First(); // or whatever query 

由于我的类型都是动态的,在动态加载的DLL中指定,我需要我的自定义json反序列化器来执行对象创建。我在answer here.

中指定了这一点

我宁愿不这样做,因为在生产中加载整个文档效率不高。

##可能的解决方案2 ##

据我所知,Lucene可用于查询类型元数据并以dynamic类型获取数据。然后我可以做一个可怕的演员并做出改变。


@ Tung-Chau后更新

谢谢Tung,遗憾的是这两种解决方案都无法解决。让我解释一下原因:

我将实体存储在:

session.Store(myDataObject);

在数据库中,将生成名为myDataObject.GetType().Name的文档。如果你这样做:

var myDataObject = session.Load<IEntity>(Id);

然后它找不到该文档,因为它没有使用名称IEntity保存,而是以动态类型的名称保存。

现在,Lucene解决方案不起作用,但原因稍微复杂一些。当Lucene找到类型(它所做的)时,Raven将其传递给custom JsonDeserialiser I mentioned。自定义Json Deserialiser无权访问元数据,因此它不知道要反映哪种类型。

当你知道类型而不是编译时,是否有更好的方法来检索数据?

谢谢。

1 个答案:

答案 0 :(得分:1)

如果您有ID(或ID):

var myDataObject = session.Load<IEntity>(Id);
//change myDataObject. Use myDataObject.GetType() as you want 
//....
session.SaveChange();

对于查询,LuceneQuery是合适的

var tag = documentStore.Conventions.GetTypeTagName(typeof(YourDataType));
var myDataObjects = session.Advanced
                 .LuceneQuery<IEntity, RavenDocumentsByEntityName>()
                 .WhereEquals("Tag", tag)
                 .AndAlso()
                  //....