使用LuceneQuery创建一个完全动态的RavenDB查询
本文关键字:动态 查询 RavenDB 一个 创建 LuceneQuery 使用 | 更新日期: 2023-09-27 18:07:07
我想要一个可以查询整个RavenDB数据库的方法。
我的方法签名是这样的:
public static DataTable GetData(string className, int amount, string orderByProperty, string filterByProperty, string filterByOperator, string filterCompare)
我想我可以用一个动态LuceneQuery来完成以上所有的工作。
session.Advanced.LuceneQuery<dynamic>();
问题是:因为我在给定的类型中使用dynamic
,我如何确保查询只包括与className匹配的类型?
我正在寻找.WhereType(className)
或.Where("type: " + className)
之类的东西。
返回正确类型的结果:
var type = Type.GetType("Business.Data.DTO." + className);
var tagName = RavenDb.GetTypeTagName(type);
using (var session = RavenDb.OpenSession())
{
var result = session.Advanced
.LuceneQuery<object, RavenDocumentsByEntityName>()
.WhereEquals("Tag", tagName)
.ToList();
}
注意,不可能添加额外的"WhereEquals"或其他过滤器。这是因为"RavenDocumentByEntityName"索引中没有包含任何特定于该文档类型的内容。
这意味着这个解决方案不能用于我想要完成的任务。
我最后做了什么
虽然它没有完全满足我的要求,但这是我最终做的:
public static List<T> GetData<T>(DataQuery query)
{
using (var session = RavenDb.OpenSession())
{
var result = session.Advanced.LuceneQuery<T>();
if (!string.IsNullOrEmpty(query.FilterByProperty))
{
if (query.FilterByOperator == "=")
{
result = result.WhereEquals(query.FilterByProperty, query.FilterCompare);
}
else if (query.FilterByOperator == "StartsWith")
{
result = result.WhereStartsWith(query.FilterByProperty, query.FilterCompare);
}
else if (query.FilterByOperator == "EndsWith")
{
result = result.WhereEndsWith(query.FilterByProperty, query.FilterCompare);
}
}
if (!string.IsNullOrEmpty(query.OrderByProperty))
{
if (query.Descending)
{
result = result.OrderBy(query.OrderByProperty);
}
else
{
result = result.OrderByDescending(query.OrderByProperty);
}
}
result = result.Skip(query.Skip).Take(query.Amount);
return result.ToList();
}
}
虽然这无疑是一个反模式,但如果您想要的话,这是一种只查看一些数据的简洁方式。很容易调用,像这样:
DataQuery query = new DataQuery
{
Amount = int.Parse(txtAmount.Text),
Skip = 0,
FilterByProperty = ddlFilterBy.SelectedValue,
FilterByOperator = ddlOperator.SelectedValue,
FilterCompare = txtCompare.Text,
OrderByProperty = ddlOrderBy.SelectedValue,
Descending = chkDescending.Checked
};
grdData.DataSource = DataService.GetData<Server>(query);
grdData.DataBind();
"Server"是我正在使用的类/文档类型之一,所以缺点是,它不是完全动态的,我必须为每个类型定义一个这样的调用。
我强烈建议你不要走这条路。您实际上是在试图隐藏RavenDB Session对象,该对象非常强大,可以直接使用。
只要看看你想要创建的方法的签名,参数都是非常严格的,并且对你正在处理的数据做出了许多可能不正确的假设。返回类型-为什么要返回DataTable
?也许返回object
或dynamic
,但Raven中没有任何东西是在表中结构化的,因此DataTable
是一个坏主意。
要回答特定的问题,类型名称来自Raven-Entity-Name
元数据,您需要在其上构建索引。当您在索引中使用from docs.YourEntity
语法进行索引时,会自动发生这种情况。当您使用动态索引(如.Query<YourEntity>
或.Advanced.LuceneQuery<YourEntity>
)时,Raven会在幕后执行此操作。
但是,你不应该这样做。