0

私はかなり長い間NHibernateを使用してきましたが、まだ「単純な」ことをするのに苦労しています。エンティティとmany-to-manyの間の関係を処理しようとしています。ServiceProviderFeatures

基本的に、すべてSERVICE_PROVIDERSのテーブルに存在する必要があるさまざまな機能を持つことができますFEATURES

これらは私のマッピングファイルです:

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>

Features

<class name="App.Domain.Feature, App.Domain" table="Features">
    <id name="Code" type="System.Guid" unsaved-value="00000000-0000-0000-0000-000000000000">
        <column name="FeatureCode" />
        <generator class="guid.comb" />
    </id>
    <property name="Description" type="AnsiString">
        <column name="Description" length="150" not-null="true" />
    </property>
    <set name="ServiceProviders" table="ServiceProvidersFeatures" cascade="none" inverse="true" lazy="true" access="field.pascalcase-underscore" optimistic-lock="false" mutable="false">
        <key column="FeatureCode"></key>
        <many-to-many class="App.Domain.ServiceProvider" column="ServiceProviderCode" not-found="ignore" />
    </set>
</class>

これらは 2 つの主要なクラスです。

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

Feature.cs

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

私がやろうとしているのは、説明が特定の文字列で始まり、少なくとも 1 つの機能 (param) が指定されているすべてのサービス プロバイダー (すべての機能を含む) を取得することです。

サブクエリが必要だと思いますが、QueryOver の作成方法がわかりません。次のようになります。

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

2 に答える 2

1

式を作成できる拡張メソッドを思いつきました。

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

この回答からのインスピレーション。

于 2013-02-19T14:40:09.583 に答える
0

あなたのスニペットで変更したいことがいくつかあります。%まず、メソッドでを指定する必要はありませんIsLike。NHibernate が自動的に指定します。次に、次の方法でサブクエリを作成できます。

var subquery = 
    session.QueryOver<App.Domain.Feature>()
           .WhereRestrictionOn(f => f.Description).IsLike("test", MatchMode.Anywhere)
           .Select(f => f.Code);

これをメインクエリにプラグインできます:

var serviceProviders = 
    session.QueryOver<App.Domain.ServiceProvider>()
           .WithSubquery.WhereProperty(s => s.Code).In(subquery)
           .List();

または、次のことを試すこともできます。

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

設定に応じて、コレクションをlazy初期化できます。Features

serviceProviders.ToList()
                .ForEach(service => NHibernateUtil.Initialize(service.Features));
于 2013-02-19T04:41:27.480 に答える