Nhibernate 如何获取子对象与多对多关系中的特定条件相匹配的实体?
我使用NHibernate已经有相当一段时间了,但仍然很难做一些“简单”的事情。我正在尝试处理我的实体Nhibernate 如何获取子对象与多对多关系中的特定条件相匹配的实体?,nhibernate,queryover,Nhibernate,Queryover,我使用NHibernate已经有相当一段时间了,但仍然很难做一些“简单”的事情。我正在尝试处理我的实体服务提供商和功能之间的多对多关系 基本上,每个服务提供商都可以有不同的功能,这些功能必须出现在我的表功能中 这些是我的映射文件: ServiceProviders.hbm.xml <class name="App.Domain.ServiceProvider, App.Domain" table="ServiceProviders"> <id name="Code" t
服务提供商
和功能
之间的多对多
关系
基本上,每个服务提供商
都可以有不同的功能,这些功能必须出现在我的表功能中
这些是我的映射文件:
ServiceProviders.hbm.xml
<class name="App.Domain.ServiceProvider, App.Domain" table="ServiceProviders">
<id name="Code" type="System.Guid" unsaved-value="00000000-0000-0000-0000-000000000000">
<column name="ServiceProviderCode" />
<generator class="guid.comb" />
</id>
<property name="Description" type="AnsiString">
<column name="Description" length="150" not-null="true" />
</property>
<set name="Features" table="ServiceProvidersFeatures" access="field.pascalcase-underscore" cascade="save-update" optimistic-lock="false">
<key column="ServiceProviderCode"></key>
<many-to-many class="App.Domain.Feature" column="FeatureCode" not-found="exception" />
</set>
</class>
这是两大类:
ServiceProvider.cs
public class ServiceProvider
{
public ServiceProvider()
{
this._Features = new HashSet<Feature>();
}
public virtual Guid Code { get; protected set; }
public virtual string Description { get; set; }
private ICollection<Feature> _Features = null;
public virtual ReadOnlyCollection<Feature> Features
{
get { return (new List<Feature>(_Features).AsReadOnly()); }
}
}
public class Feature
{
public Feature()
{
this._ServiceProviders = new HashSet<ServiceProvider>();
}
public virtual Guid Code { get; protected set; }
public virtual string Description { get; set; }
private ICollection<ServiceProvider> _ServiceProviders = null;
public virtual ReadOnlyCollection<ServiceProvider> ServiceProviders
{
get { return (new List<ServiceProvider>(_ServiceProviders).AsReadOnly()); }
}
}
我试图做的是获取描述以某个字符串开头的所有服务提供者(具有所有特性),并且它们至少指定了一个特性(param)
我想我需要一个子查询,但我不知道如何构建查询覆盖。应该是这样的:
var serviceProviders =
session.QueryOver<App.Domain.ServiceProvider>()
.Inner.JoinAlias(x => x.Features, () => features)
.WhereRestrictionOn(f => f.Description).IsLike("%" + "test" + "%")
.AndRestrictionOn(() => features.Code).IsIn(<SubQuery>)
.List();
App.Domain.ServiceProvider serviceProvider = null;
App.Domain.Feature features = null;
App.Domain.Language languages = null;
App.Domain.Service services = null;
Guid[] selectedFeatures = {};
var serviceProviders = Session.QueryOver(() => serviceProvider);
serviceProviders
.AttachWhereForSearchText(<searchText>)
.AttachWhereForFeatures(serviceProvider, features, selectedFeatures);
Results = serviceProviders
.TransformUsing(Transformers.DistinctRootEntity)
.Take(<pageSize>)
.Skip((<page> - 1) * <pageSize>)
.ToList<App.Domain.ServiceProvider>();
var服务提供者=
session.QueryOver()
.Inner.JoinAlias(x=>x.Features,()=>Features)
.WhereRestrictionOn(f=>f.Description).IsLike(“%”+“test”+“%”)
.AndRestrictionOn(()=>features.Code).IsIn()
.List();
在您的代码片段中,有几点我想更改。首先,您不需要在IsLike
方法中指定%
:NHibernate会自动执行此操作。
其次,可以按以下方式构造子查询:
var subquery =
session.QueryOver<App.Domain.Feature>()
.WhereRestrictionOn(f => f.Description).IsLike("test", MatchMode.Anywhere)
.Select(f => f.Code);
我提出了一种扩展方法,允许我构建表达式:
public static class ServiceProviderSearch
{
public static IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> AttachWhereForSearchText(this IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> mainQuery, string searchText)
{
if (!string.IsNullOrEmpty(searchText))
{
ICriterion filterSearchText = Expression.Disjunction()
.Add(Restrictions.On<App.Domain.ServiceProvider>(f => f.Description).IsLike(searchText, MatchMode.Anywhere))
.Add(Restrictions.On<App.Domain.ServiceProvider>(f => f.ExtendedDescription).IsLike(searchText, MatchMode.Anywhere));
mainQuery.Where(filterSearchText);
}
return (mainQuery);
}
public static IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> AttachWhereForFeatures(this IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> mainQuery, App.Domain.ServiceProvider serviceProvider, App.Domain.Feature features, Guid[] listOfFeatures)
{
if ((listOfFeatures != null) && (listOfFeatures.Count() > 0))
{
mainQuery
.Inner.JoinAlias(() => serviceProvider.Features, () => features);
mainQuery.WithSubquery.WhereProperty(() => features.Code)
.In(
QueryOver.Of<App.Domain.Feature>()
.WhereRestrictionOn(f => f.Code)
.IsIn(listOfFeatures)
.Select(f => f.Code)
);
}
return (mainQuery);
}
}
公共静态类ServiceProviderSearch
{
公共静态IQueryOver。我认为您的建议不起作用。特别是在第一个示例中。WhereRestrictionOn(s=>s.code).IsIn(子查询)
此语法不起作用。所有语法都试过了吗?我不确定语法,因为我没有关闭编译器,但基于它们应该能起作用。你是对的,我在第一个查询中犯了错误(我觉得可以这样构造它)。更新了我的答案。可能我遗漏了什么,但内部连接将满足至少指定一个功能的要求。感谢您的评论Jamie。问题是,如果搜索中至少包含一个功能,我想查看所有功能。
var serviceProviders =
session.QueryOver<App.Domain.ServiceProvider>()
.JoinQueryOver<App.Domain.Feature>(s => s.Features)
.WhereRestrictionOn(f => f.Description).IsLike("test", MatchMode.Anywhere)
.List<App.Domain.ServiceProvider>();
serviceProviders.ToList()
.ForEach(service => NHibernateUtil.Initialize(service.Features));
public static class ServiceProviderSearch
{
public static IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> AttachWhereForSearchText(this IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> mainQuery, string searchText)
{
if (!string.IsNullOrEmpty(searchText))
{
ICriterion filterSearchText = Expression.Disjunction()
.Add(Restrictions.On<App.Domain.ServiceProvider>(f => f.Description).IsLike(searchText, MatchMode.Anywhere))
.Add(Restrictions.On<App.Domain.ServiceProvider>(f => f.ExtendedDescription).IsLike(searchText, MatchMode.Anywhere));
mainQuery.Where(filterSearchText);
}
return (mainQuery);
}
public static IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> AttachWhereForFeatures(this IQueryOver<App.Domain.ServiceProvider, App.Domain.ServiceProvider> mainQuery, App.Domain.ServiceProvider serviceProvider, App.Domain.Feature features, Guid[] listOfFeatures)
{
if ((listOfFeatures != null) && (listOfFeatures.Count() > 0))
{
mainQuery
.Inner.JoinAlias(() => serviceProvider.Features, () => features);
mainQuery.WithSubquery.WhereProperty(() => features.Code)
.In(
QueryOver.Of<App.Domain.Feature>()
.WhereRestrictionOn(f => f.Code)
.IsIn(listOfFeatures)
.Select(f => f.Code)
);
}
return (mainQuery);
}
}
App.Domain.ServiceProvider serviceProvider = null;
App.Domain.Feature features = null;
App.Domain.Language languages = null;
App.Domain.Service services = null;
Guid[] selectedFeatures = {};
var serviceProviders = Session.QueryOver(() => serviceProvider);
serviceProviders
.AttachWhereForSearchText(<searchText>)
.AttachWhereForFeatures(serviceProvider, features, selectedFeatures);
Results = serviceProviders
.TransformUsing(Transformers.DistinctRootEntity)
.Take(<pageSize>)
.Skip((<page> - 1) * <pageSize>)
.ToList<App.Domain.ServiceProvider>();