How can I select a column within a dictionary value with nhibernate?

江枫思渺然 提交于 2019-12-06 06:01:30
Radim Köhler

For these cases, NHibernate has very nice solution: 18.1. NHibernate filters. At the end, we will select Product and apply filter on the dictionary... therefore having only SingleOrDefault() item in the Locales.

Definiton of the Filter

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

and apply it

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

From that moment, whenever you enable the filter in the session (even with some AOP filter), you can be sure that the IDictionary contains exactly one (or none) element..

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

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

There is similar posts with some more links if needed https://stackoverflow.com/a/17109300/1679310

EDIT: Restricting the column "Locale" directly, getting the list of Names

Other approach (keeping the current solution almost the same) which could be used (and I know about) is to extend the LocalEntity mapping

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);
            }
        );
    }
}

Having this, we can get the list of all "en" Names like this:

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>();

Now we have a list containing all the Names from EntityLocale filtered by "en" culture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!