如何使用nhibernate选择字典值中的列
本文关键字:字典 何使用 nhibernate 选择 | 更新日期: 2023-09-27 18:19:19
我有一个类似的结构:
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过滤器。最后,我们将选择Product
并在字典上应用过滤器…因此在Locales
中只有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"))
;
从那时起,无论何时在会话中启用过滤器(即使使用一些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
编辑:限制列"Locale"直接获取Names列表
另一种可以使用的方法(保持当前解决方案几乎相同)是扩展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的Names
,并通过"en"文化