c# - 如何使用 nhibernate 选择字典值中的列?

标签 c# nhibernate queryover nhibernate-criteria

我的结构与此类似:

public class Entity
{
    public int Id { get; set; }
    public IDictionary<string, EntityLocale> Locales { get; set; }
}
public class EntityLocale
{
    public string Name { get; set; }
}
public class EntityMap : ClassMap<Entity>
{
    public EntityMap()
    {
        HasMany(x => x.Locales)
                .AsMap<string>("Locale")
                .Component(
                c => {
                         c.Map(x => x.Name);
                     }
                );
    }
}

我想接收带有“en”键的产品区域设置的所有名称。使用 linq 它将是:

var names = Session.QueryOver<Product>().List().Select(x => x.Locales["en"].Name).ToList();

如何使用 nhibernate 实现此目的? (我不在乎它是 QueryOver 还是 Criteria api,我只是不想选择所有内容)。

更新

我想出了以下丑陋的 hack(我对此不满意,我不想在我的代码中包含任何 sql):

var names = Session.CreateSQLQuery("SELECT Name FROM ProductLocales WHERE Locale = 'en'").List<string>()

最佳答案

对于这些情况,NHibernate 有非常好的解决方案:18.1. NHibernate filters 。最后,我们将选择 Product 并对字典应用过滤器...因此 中只有 SingleOrDefault() 项区域设置

过滤器的定义

public class CulturFilter : FilterDefinition
{
  public CulturFilter()
  {
    WithName("CulturFilter")
        .AddParameter("culture",NHibernate.NHibernateUtil.String);
  }
}

并应用它

HasMany(x => x.Locales)
  .AsMap<string>("Locale")
  ... 
  .ApplyFilter<CulturFilter>("Locale = :culture"))
;

从那一刻起,每当您在 session 中启用过滤器(即使使用某些 AOP 过滤器)时,您都可以确定 IDictionary 只包含一个(或不包含)元素。

session.EnableFilter("CultureFilter")
    .SetParameter("culture", "en");

// applied every time
var criteria = session.CreateCritieria...
var query = session.QueryOver....

如果需要的话,还有类似的帖子和更多链接https://stackoverflow.com/a/17109300/1679310

编辑:直接限制“区域设置”列,获取名称列表

可以使用(我知道)的其他方法(保持当前解决方案几乎相同)是扩展 LocalEntity 映射

public class EntityLocale
{
    public virtual string CultureName { get; set; }
    public virtual string Name { get; set; }
}
public class EntityMap : ClassMap<Entity>
{
    public EntityMap()
    {
        HasMany(x => x.Locales)
            .AsMap<string>("Locale")
            .Component(
            c => {
                c.Map(x => x.CultureName).Formula("Locale").Not.Insert().Not.Update();
                c.Map(x => x.Name);
            }
        );
    }
}

有了这个,我们就可以获得所有“en”名称的列表,如下所示:

var criteria = 
    session.QueryOver<Entity>()
    .JoinQueryOver<IDictionary<string, EntityLocale>>(c => c.Locales)
    .UnderlyingCriteria;

var list = criteria
    .Add(Restrictions.Eq("CultureName", "en"))
    .SetProjection(Projections.SqlProjection("Name"
        , new string[] { "name" }
        , new IType[] { NHibernateUtil.String }))
    .List()
    .Cast<string>()
    .ToList<String>();

现在我们有一个列表,其中包含 EntityLocale 中按“en”文化过滤的所有名称

关于c# - 如何使用 nhibernate 选择字典值中的列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17240037/

相关文章:

nhibernate - ToRowCountQuery 似乎忽略分组

c# - UWP 应用程序更快地加载图像?

c# - Linq、lambda 和@

c# - N休眠: QueryOver in generic method

c# - 如何在 C# 中的 List<string> 上切换大小写

c# - 带子查询的 NHibernate Linq 返回 'Only one expression can be specified in the select list when the subquery is not introduced with EXISTS'

nhibernate - QueryOver by join and add conditions by Independent if

c# - c#生成1到100整数数组的简洁方法

c# - 如果进程意外终止,作为 SqlTransaction 或 TransactionScope 基础的事务是否会回滚?

entity-framework - Code First Entity Framework 或 NHibernate