общая сетка данных фильтрации - PullRequest
1 голос
/ 06 января 2011

Я работал над общим решением для фильтрации данных с помощью Nhibernate.Код выглядит так:

private ICriteria GetPagedCriteria<T>(GridResult<T> GridResult, bool sort)
        {
            var query = Session.CreateCriteria(typeof(T));

            foreach (string alias in GridResult.NHibernatePaths)
            {
                query.CreateAlias(alias, alias.Replace(".", "_"));
            }

            foreach (PropertyValueOperators pvo in GridResult.FilterList)
            {
                if(String.IsNullOrEmpty(pvo.Value) == false)
                {
                    switch (pvo.LikeOperator)
                    {
                        case "Contains":
                            query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), String.Format("%{0}%",pvo.Value), MatchMode.Exact));
                        break;
                        case "EndsWith":
                            query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), String.Format("%{0}", pvo.Value), MatchMode.Exact));
                        break;
                        case "Equals":
                            query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), pvo.Value, MatchMode.Exact));
                        break;
                        case "Starts With":
                            query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), String.Format("{0}%", pvo.Value), MatchMode.Exact));
                        break;
                        default:
                            throw new ArgumentException("LikeOperator not recognised");
                    }
                }
            }

            if (sort)
            {
                foreach (var pair in GridResult.SortList)
                {
                    var func = pair.Value
                       ? new Func<string, NHibernate.Criterion.Order>(NHibernate.Criterion.Order.Asc)
                       : new Func<string, NHibernate.Criterion.Order>(NHibernate.Criterion.Order.Desc);
                    query.AddOrder(func(pair.Key));
                }
            }

            return query;
        }

К сожалению, это создает SQL с большим количеством «лайков» и «забрасываний», что очень неэффективно.Как и следовало ожидать, я знаю ... Я еще не эксперт NHibernate, поэтому буду признателен за любые комментарии, чтобы сделать это общее решение более эффективным.Большое спасибо заранее.

Кристиан

Ответы [ 2 ]

2 голосов
/ 07 января 2011

Нет способа избежать использования подобных операторов в вашем случае. Ну, оператор Equal прост, «начинается с», который переводится в «подобное» значение% ', также будет эффективным, так как оно соответствует левой стороне и может использовать индекс, «Содержит» и «Заканчивается на» должны быть переведены на подобные операции, как вы уже реализовали.

Если вы действительно хотите избежать поиска по аналогии, вы должны изменить свой подход - не используйте CriteriaAPI и используйте Lucene.NET с NHibernate.Search, который может лучше соответствовать вашим потребностям. Я не использовал их в производственном проекте, но они кажутся идеальными.

1 голос
/ 06 января 2011

Содержит, Endswith и Startswith не могут быть преобразованы в нечто подобное в sql без like. База данных sql не идеальна для такого рода запросов. Вы можете лучше использовать поисковую базу данных, такую ​​как Lucene, в сочетании с NHiberante.Search

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...