Limit collection to retrieve only recent entries f

2019-02-25 00:32发布

The User entity can have thousands of UserOperations. Sometimes I don't want to retrieve (for readonly entity) all of them but only "the recent 10 OR not completed".

public class SimpleForm
{
    public class User : EntityBase
    {
        //  ...

        private ISet<UserOperation> _recentOperations = new HashedSet<UserOperation>();
        public virtual ISet<UserOperation> RecentOperations { get { return _recentOperations; } set { _recentOperations = value; } }
    }
}

So how can I specify it? I think I could use mapping overrides?

I understand I could make this with a seperate query but can it be done by entity mapping?

Also I wonder if there is a possibility to do the some for non-readonly entity where I can modify the collection of operations?

UPDATE

I tried to use

DateTime dateTime = (DateTime.UtcNow - TimeSpan.FromDays(15));
mapping.HasMany(x => x.RecentOperations)
       .Where(x => x.EndedAt == null || x.EndedAt < dateTime);

but it says "Unable to convert expression to SQL".

I replaced it with

mapping.HasMany(x => x.RecentOperations)
                .Where(x => x.EndedAt == null);

and now it throws null reference exception inside

в FluentNHibernate.Utils.ExpressionToSql.Convert(Object value) в FluentNHibernate.Utils.ExpressionToSql.Convert(ConstantExpression expression) в FluentNHibernate.Utils.ExpressionToSql.Convert[T](Expression`1 expression, UnaryExpression body)

1条回答
甜甜的少女心
2楼-- · 2019-02-25 01:06

There are 2 general ways how to filter mapped collections.

The first is a bit rigid, fixed, in a mapping defined where="" clause:

The second and maybe really suitable in this scenario, is dynamic version called filter:

NHibernate adds the ability to pre-define filter criteria and attach those filters at both a class and a collection level. A filter criteria is the ability to define a restriction clause very similiar to the existing "where" attribute available on the class and various collection elements. Except these filter conditions can be parameterized. The application can then make the decision at runtime whether given filters should be enabled and what their parameter values should be. Filters can be used like database views, but parameterized inside the application....

The implementation in fluent would look like this:

public class RecentFilter : FilterDefinition
{
    public RecentFilter()
    {
        WithName("RecentFilter")
            .WithCondition("( :EndedAtDate IS NULL OR EndedAt < :EndedAtDate )")
            .AddParameter("EndedAtDate",NHibernate.NHibernateUtil.DateTime);
    }
}

this is the filter, and here is its usage in a fluent mapping:

mapping
   .HasMany(x => x.RecentOperations)
   ...
   .ApplyFilter<RecentFilter>();

In runtime, we can turn filter on/off on the ISession level:

session.EnableFilter("RecentFilter")
       .SetParameter("EndedAtDate",DateTime.Now.AddDays(-15));

See also:

查看更多
登录 后发表回答