2017-04-26 62 views
0

我试图简化和压缩我的代码,并尽可能地消除代码重复。我有一个查询RavenDB集合的方法,查询需要适应我要查询的类型。此类型根据传递给方法的参数而变化,并且where子句也需要适应。 我有一个基础类型AdministrativeArea,其他类型派生自(Level1_AdministrativeAreas到Level5_AdministrativeAreas)。根据不同的情况下,我需要查询AdministrativeAreas,Level1_AdministrativeAreas等使用RavenDB查询的动态参数

我目前有:

private void Merge(MergeLevel currentMergeLevel, IDocumentSession currentSession) 
    { 
    (...) 
IQueryable<AdministrativeArea> query; 
    if (currentMergeLevel == MergeLevel.Level1) 
     query = currentSession.Query<AdministrativeArea, AdminAreaName>() 
     .Where(area => !string.IsNullOrEmpty(area.NAME_0) && !string.IsNullOrEmpty(area.NAME_1)); 
    (...) 
    } 

有没有办法在类型传递作为方法参数,并让它们应用到查询时,这样的:

private void Merge(MergeLevel currentMergeLevel, IDocumentSession currentSession, Type requiredType, Type indexType) 
    { 
     (...) 
    IQueryable<requiredType> query; 
     if (currentMergeLevel == MergeLevel.Level1) 
      query = currentSession.Query<requiredType, indexType>() 
      .Where(area => !string.IsNullOrEmpty(area.NAME_0) && !string.IsNullOrEmpty(area.NAME_1)); 
     (...) 
     } 

我面临在编译时的几个问题,即“是可变的,但是,使用像类型”,而事实上,成员变量(NAME_0,NAME_1等)可以”因为编译器不知道“将要发生什么”,因此可以推断。 我怀疑这是根本无法完成的;但是,这对代码维护有影响,因为我必须为每种类型的查询创建不同的方法,或者创建一个相当大的方法。这两者都不太吸引人,但我没有看到任何方式。

+1

这不是很清楚,但尝试使用泛型:void Merge (int currentMergeLevel ,IDocumentSession currentSession) – Embri

回答

0

按类型过滤的一种好方法是在索引的“select”子句中包含Raven-Entity-Name字段。 然后,您将能够通过使用EntityType字段来过滤类型。 你可以看到这种指标的例子在内置乌鸦/ DocumentsByEntityName指数

所以,你的指数可能是这样的:

from doc in docs 
let entityType = doc["@metadata"]["Raven-Entity-Name"] 
where entityType.EndsWith("_AdministrativeAreas") 
select new 
{ 
    EntityType = entityType, 
    //the rest of the fields 
} 

请注意,这会工作如果你通过现有的客户端API插入文档(原始REST API不会自己添加Raven-Entity-Name)

+0

迈克尔,这是一个有趣的方法 - 我没有想到这一点!我结束了对泛型的熟悉,结果为我的问题提供了一个解决方案。不过,我会玩弄你的建议方法。谢谢 ! –