【问题标题】:How to Reduce number of parameters using NHibernate Criterion如何使用 NHibernate Criterion 减少参数数量
【发布时间】:2016-01-20 09:42:50
【问题描述】:

我正在尝试查询一个 PropertyBag 表,其中包含 25 fieldNames 'FieldName1, FieldName2 ... FieldName25' 和 25 FieldValues 'FieldValueString1, FieldValueString2 ... FieldValueString25'

很遗憾,我无法更改设计,只能更改我们查询数据的方式。

现在我们这样查询它:

static DetachedCriteria CreateFieldValueBagDetachedCriteria(string field, object value)
{
    ICriterion criterionBag = Expression.Sql("0=1");
    for (int slotNr = 1 ; slotNr <= 25 ; slotNr++) 
    {
        ICriterion valueEqCritBag = Restrictions.InsensitiveLike(string.Format("FieldValueString{0}", slotNr), returnWildCardString( (string)value), MatchMode.Exact);
        ICriterion fieldNameEqCrit = Restrictions.Eq("FieldName" + slotNr, field);
        criterionBag = Restrictions.Or(Restrictions.And(fieldNameEqCrit, valueEqCritBag), criterionBag);
    }
    return criterionBag;
}

这将导致 50 个参数在 25 次中都是相同的 2 个值。

有没有办法重写这段代码来减少参数的数量?

【问题讨论】:

    标签: c# sql nhibernate


    【解决方案1】:

    我能想到的最简单的方法是编写一个共享参数的特殊投影。然而,由于 LikeExpression 不将投影作为值,我们也必须自己编写:

    [Serializable]
    public class SharingConstantProjection : SimpleProjection
    {
        private readonly TypedValue _typedValue;
        private NHibernate.SqlCommand.Parameter _parameter;
    
        public SharingConstantProjection(object value)
            : this(value, NHibernateUtil.GuessType(value.GetType()))
        {
        }
    
        public SharingConstantProjection(object value, IType type)
        {
            _typedValue = new TypedValue(type, value, EntityMode.Poco);
        }
    
        public override bool IsAggregate
        {
            get { return false; }
        }
    
        public override SqlString ToGroupSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
        {
            throw new InvalidOperationException("not a grouping projection");
        }
    
        public override bool IsGrouped
        {
            get { return false; }
        }
    
        public override SqlString ToSqlString(ICriteria criteria, int position, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
        {
            if (_parameter == null)
                _parameter = criteriaQuery.NewQueryParameter(_typedValue).Single();
    
            return new SqlString(
                _parameter,
                " as ",
                GetColumnAliases(position, criteria, criteriaQuery)[0]);
        }
    
        public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
        {
            return new IType[] { _typedValue.Type };
        }
    
        public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
        {
            return new TypedValue[] { _typedValue };
        }
    
        public override string ToString()
        {
            return (_typedValue.Value ?? "NULL").ToString();
        }
    }
    
    [Serializable]
    public class MyInsensitiveLikeExpression : AbstractCriterion
    {
        private readonly IProjection _projection;
        private readonly IProjection _value;
    
        public MyInsensitiveLikeExpression(string propertyName, string value)
            : this(Projections.Property(propertyName), Projections.Constant(value))
        { }
    
        public MyInsensitiveLikeExpression(string propertyName, IProjection value)
            : this(Projections.Property(propertyName), value)
        { }
    
        public MyInsensitiveLikeExpression(IProjection projection, IProjection value)
        {
            _projection = projection;
            _value = value;
        }
    
        #region ICriterion Members
    
        public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
        {
            SqlString[] columns = CriterionUtil.GetColumnNames(null, _projection, criteriaQuery, criteria, enabledFilters);
            if (columns.Length != 1)
                throw new HibernateException("Like may only be used with single-column properties / projections.");
    
            var value = SqlStringHelper.RemoveAsAliasesFromSql(_value.ToSqlString(criteria, 0, criteriaQuery, enabledFilters));
    
            var dialect = criteriaQuery.Factory.Dialect;
            var builder = new SqlStringBuilder(8)
                .Add(dialect.LowercaseFunction)
                .Add(StringHelper.OpenParen)
                .Add(columns[0])
                .Add(StringHelper.ClosedParen)
                .Add(" like ")
                .Add(dialect.LowercaseFunction)
                .Add(StringHelper.OpenParen)
                .Add(value)
                .Add(StringHelper.ClosedParen);
    
            return builder.ToSqlString();
        }
    
        public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
        {
            return _value.GetTypedValues(criteria, criteriaQuery);
        }
    
        public override IProjection[] GetProjections()
        {
            return new IProjection[] { _projection };
        }
    
        #endregion
    
        public override string ToString()
        {
            return _projection + " like " + _value;
        }
    }
    

    并像使用它

    var foo = new SharingConstantProjection("foo");
    session.CreateCriteria<User>()
        .Add(new MyInsensitiveLikeExpression(Projections.Property<User>(u => u.Name), foo) || new MyInsensitiveLikeExpression(Projections.Property<User>(u => u.Email), foo))
        .List();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 2012-01-30
      • 2018-04-16
      • 2019-07-28
      • 2022-08-15
      • 1970-01-01
      相关资源
      最近更新 更多