【问题标题】:Fluent NHibernate dynamic DTO queryFluent NHibernate 动态 DTO 查询
【发布时间】:2018-04-16 10:14:23
【问题描述】:

我正在尝试使用 Fluent NHibernate 编写动态查询,并努力弄清楚如何应用动态 where 条件。

这是一个 ASP.NET MVC5 项目,我希望在视图中显示一个 DTO 表,让用户能够对任何行应用过滤器。出于性能原因,必须将过滤器传递给数据库。

假设我有以下类定义:

// Entity in database
public class EntityA
{
    public int Id {get; set;}
    public string Name {get; set;}
    public IEnumerable<EntityB> Children {get; set;}
}

// Entity in database
public class EntityB
{
    public int Id {get; set;}
    public string Name {get; set;}
    public EntityA Parent {get; set;}
}

// DTO that is displayed in view / filter criteria is based on
public class Dto
{
    public int Id {get; set;}
    public string AName {get; set;}
    public string BName {get; set;}
}

我在IEnumerable&lt;FilterProperty&gt; 中收到用户的过滤条件,如下所示:

public class FilterProperty
{
    public string Name {get; set;}
    public dynamic Value {get; set;}
}

我的 NHibernate 查询如下:

EntityA aliasA = null;
EntityB aliasB = null;
Dto aliasDto = null;

var query = QueryOver.Of(() => aliasB)
    .JoinAlias(() => aliasA.Parent, () => aliasA)
    .SelectList(l => l
        .Select(() => aliasB.Id).WithAlias(() => aliasDto.Id)
        .Select(() => aliasA.Name).WithAlias(() => aliasDto.AName)
        .Select(() => aliasB.Name).WithAlias(() => aliasDto.BName)
    )
    .TransformUsing(Transformers.AliasToBean<Dto>());

我感到困惑的是,如何将针对 DTO 的过滤器的平面列表转换为针对可以传递给 .Where() NHibernate 方法的实体对象的表达式树? p>

是否可以在转换后应用限制条件?

【问题讨论】:

  • 您的过滤器应该如何连接?使用&amp;&amp;||?
  • 所有过滤器将&amp;&amp;在同一级别。

标签: c# nhibernate fluent-nhibernate queryover


【解决方案1】:

1。创建过滤条件。

您可能希望为此创建单独的方法/帮助程序/转换器。

    Dictionary<string, string> mappings = new Dictionary<string, string>(){
       {"Id",    "aliasB.Id"},
       {"AName", "aliasA.Name"},
       {"BName", "aliasB.Name"}
    };
    List<FilterProperty> filters = new List<FilterProperty>();
    Junction filterCreteria = Restrictions.Conjunction();
    foreach (var filter in filters)
    {
        var mappedPropertyName = mappings[filter.Name];
        filterCreteria.Add(Restrictions.Eq(mappedPropertyName, filter.Value));
    }

2。在您的查询中使用它:

 .Where(filterCreteria)

【讨论】:

  • 这样做会引发NHibernate.QueryException,因为 DTO 的属性名称与底层实体对象不匹配。
  • 在这种情况下,您需要以某种方式实现从 DTO 属性到实体属性的转换(可以通过简单的字典、删除前缀或更复杂的方法来完成)。
  • 谢谢 - 像这样手动映射 DTO 属性是唯一的方法吗?如果可能,我想使用 DTO 属性名称过滤投影结果集。这当然可以使用 Entity Framework。
  • 恐怕 NHibernate 不可能。您只能提供实体属性进行过滤(如果您想在数据库级别过滤数据)。 select 语句中的别名用于将原始值(过滤后)投影到 DTO 模型。
  • 好的,谢谢 - 如果你更新你的答案说不可能动态地做到这一点,我会标记为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 2022-08-23
相关资源
最近更新 更多