我通过反射动态加载类型,实例化类,用数据填充它们,然后将它们保存到 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 反序列化器来执行对象创建。我在这里的答案中指定了这一点。
我宁愿不这样做,因为在生产中加载整个文档效率不高。
## 可能的解决方案 2 ##
我了解可以使用 Lucene 来查询类型元数据并将数据作为dynamic
类型取出。然后我可以做一个可怕的演员并做出改变。
@Tung-Chau 之后更新
感谢 Tung,不幸的是,这两种解决方案都不起作用。让我解释一下原因:
我将实体存储在:
session.Store(myDataObject);
在数据库中,这将生成一个名为myDataObject.GetType().Name
. 如果你这样做:
var myDataObject = session.Load<IEntity>(Id);
然后它不会找到该文档,因为它不是以名称保存的IEntity
,而是以动态类型的名称保存的。
现在 Lucene 解决方案也不起作用,但原因稍微复杂一些。当 Lucene 找到类型时(它确实找到了),Raven 将它传递给我提到的自定义 JsonDeserialiser。自定义的 Json Deserialiser 无法访问元数据,因此它不知道要反映哪种类型。
当您知道类型但在编译时不知道时,是否有更好的方法来检索数据?
谢谢你。