Я пытаюсь выбрать лучший шаблон для доступа к данным в моем приложении MVC. В настоящее время, следуя серии хранилищ MVC, я использую репозитории, подвергая IQueryable уровню сервиса, который затем применяет фильтры. Первоначально я использовал LINQtoSQL, например.
public interface IMyRepository
{
IQueryable<MyClass> GetAll();
}
Реализовано в:
public class LINQtoSQLRepository : IMyRepository
{
public IQueryable<MyClass> GetAll()
{
return from table in dbContext.table
select new MyClass
{
Field1 = table.field1,
... etc.
}
}
}
Фильтр для идентификаторов:
public static class TableFilters
{
public static MyClass WithID(this IQueryable<MyClass> qry, string id)
{
return (from t in qry
where t.ID == id
select t).SingleOrDefault();
}
}
Вызывается из службы:
public class TableService
{
public MyClass RecordsByID(string id)
{
return _repository.GetAll()
.WithID(id);
}
}
У меня возникла проблема, когда я экспериментировал с реализацией репозитория с использованием Entity Framework с LINQ to Entities. Класс filter в моем проекте содержит более сложные операции, чем "WHERE... ==..." в приведенном выше примере, который, как мне кажется, требует разных реализаций в зависимости от поставщика LINQ. В частности, у меня есть требование выполнить предложение SQL "WHERE... IN...". Я могу реализовать это в классе фильтра, используя:
string[] aParams = // array of IDs
qry = qry.Where(t => aParams.Contains(t.ID));
Однако для того, чтобы выполнить это против Entity Framework, мне нужно предоставить решение, такое как BuildContainsExpression, привязанное к платформе Entity Framework, Это означает, что у меня должно быть две различные реализации этого конкретного фильтра, в зависимости от основного поставщика.
Буду признателен за любые советы о том, как я должен исходить отсюда. Мне показалось, что разоблачение IQueryable из моего репозитория позволит мне выполнять фильтры на нем, независимо от базового провайдера, что позволяет мне переключаться между провайдерами, если и когда это необходимо. Однако описанная выше проблема заставляет меня думать, что я должен выполнять всю свою фильтрацию в репозиториях и возвращать IEnumerable, IList или отдельные классы.
Большое спасибо, Matt