Шаблон спецификации для запросов к базе данных с использованием NHibernate
-
20-08-2019 - |
Вопрос
Как реализовать шаблон спецификации для запроса базы данных с использованием NHibernate? (без LINQ to NHibernate). Я много читал о шаблоне спецификации, но большинство из них было посвящено проверке и запросу объектов коллекции памяти.
Насколько я знаю, лучший способ использовать DetachedCriteria в интерфейсе спецификации, например этот.
interface ISpecification<T> {
bool IsSatisfiedBy(T object);
DetachedCriteria CreateCriteria();
}
Есть ли альтернатива или лучший способ сделать это?
Решение
Это не обязательно лучше, но может быть альтернативой
interface ISpecification<T>
{
bool IsSatisfiedBy(T object);
Expression<Func<T, bool>> Predicate { get; }
}
Легко использовать поверх linq (для перехода в спящий режим) и коллекций памяти.
Другие советы
Я реализовал это, используя простой метод расширения и шаблон спецификации, который работает для списков System.Linq.IQueryable.
public interface IFilter<in T>
{
bool MatchFilter(T o);
}
public static class FilterExtension
{
public static IQueryable<T> Filter<T>(this IQueryable<T> query, IFilter<T> filter)
{
return query.Where(x => filter.MatchFilter(x));
}
}
Простые примеры классов и реализация IFilter:
public class Organization
{
public string Name { get; set; }
public string Code { get; set; }
public Address Address { get; set; }
public Organization(string name, string code, string city, string country)
{
Name = name;
Code = code;
Address = new Address(city, country);
}
}
public class Address
{
public Address(string city, string country)
{
City = city;
Country = country;
}
public string City { get; set; }
public string Country { get; set; }
}
public class GenericOrganizationFilter : IFilter<Organization>
{
public string FilterString { get; set; }
public GenericOrganizationFilter(string filterString)
{
FilterString = filterString;
}
public bool MatchFilter(Organization o)
{
return
(o.Name != null && o.Name.Contains(FilterString)) ||
(o.Code != null && o.Code.Contains(FilterString)) ||
(o.Address != null && o.Address.City != null && o.Address.City.Contains(FilterString)) ||
(o.Address != null && o.Address.Country != null && o.Address.Country.Contains(FilterString));
}
}
Использование:
IFilter<Organization> filter = new GenericOrganizationFilter("search string");
//Assuming queryable is an instance of IQueryable<Organization>.
IQueryable<Organization> filtered = queryable.Filter(filter);