Ваш вопрос содержит неверное утверждение: верно то, что POCO не зависят от IObjectSet.
Сами POCO независимы от EF. Или лучше: они должны быть независимыми от EF. Поскольку ВЫ реализуете классы POCO, вы, наконец, несете ответственность за это. (В противном случае термин POCO был бы неправильным.)
Если вы используете стандартный шаблон T4 для создания классов POCO из описания модели вместо того, чтобы писать классы самостоятельно, шаблон гарантирует, что классы не зависят от EF - они не являются производными от Entity
и коллекции как члены класса генерируются с ICollection
по этому шаблону, а не с IObjectSet.
Шаблон репозитория это другой вопрос. Шаблон POCO T4 не создает репозиторий в качестве абстрактного интерфейса для работы с базой данных с POCO. Он создает производный ObjectContext, который является скорее специфической для EF реализацией возможного интерфейса репозитория (или, по крайней мере, помогает легко реализовать возможный интерфейс репозитория).
Если вы хотите иметь интерфейс репозитория, который не зависит от EF или LINQ, вы должны определить его таким образом. Ничто не заставляет вас использовать IObjectSet или IQueryable в этом интерфейсе. Возможно, примеры реализации шаблона репозитория, который вы видели, не предполагали быть независимыми от Entity Framework или LINQ.
Пример:
Предположим, что на вашем бизнес-уровне вам необходим список всех продуктов данной категории, возвращаемых из уровня персистентности. Что бы этот слой выставил для выполнения запроса?
Если вы имеете в виду только те базы данных, которые предлагают поставщика LINQ, вы можете сконструировать интерфейс хранилища следующим образом:
public interface IProductsRepository
{
IQueryable<Product> AllProducts { get; } // Product is the POCO class
}
Конкретная реализация этого репозитория, основанная на EF, просто вернула бы ObjectSet<Product>
из ObjectContext, который действительно создал шаблон T4.
И ваш бизнес-уровень выполняет запрос следующим образом:
IProductsRepository rep = new SomeConcreteImplementationOfProductsRepository();
IList productsOfCategory =
rep.AllProducts.Select(p => p.Category == "stuff").ToList();
Но если вы хотите быть более открытым, какой тип персистентного хранилища вы хотите поддерживать, может быть лучше спроектировать хранилище независимо от IQueryable. Следствием этого может быть то, что вашему абстрактному интерфейсу репозитория требуются более конкретные методы для ответа на запросы бизнес-уровня, например, вам нужно сейчас:
public interface IProductsRepository
{
IList<Product> GetProductsOfCategory(string category);
}
и бизнес-уровень делает это:
IProductsRepository rep = new SomeConcreteImplementationOfProductsRepository();
IList productsOfCategory = rep.GetProductsOfCategory("stuff");
Конкретная реализация этого репозитория с использованием EF (или другой платформы данных, поддерживающей LINQ) может по-прежнему использовать запрос LINQ, как это делал бизнес-уровень в первом примере. Но другие реализации могут работать по-другому (скажем, у вас есть «база данных», в которой продукты хранятся в одном текстовом файле на категорию. Затем реализация для этого метода интерфейса считывает один конкретный файл с диска. Или ваша реализация репозитория запрашивает веб-сервис для данные и тд ...)
Ключевой момент: если вы используете классы POCO, вы открыты для всех этих типов репозиториев. EF с поддержкой POCO не заставляет вас создавать интерфейсы репозитория на основе IQueryable или даже IObjectSet. Наконец, все зависит от того, какие уровни устойчивости вы имеете в виду. Чем больше они отличаются, тем более специфические методы вам могут понадобиться в интерфейсе репозитория, и тем больше работы вам потребуется для реализации этих методов. Использование IQueryable является удобным компромиссом, который позволяет определить простой интерфейс репозитория, в то же время позволяя EF реализовывать простые реализации, а также другие базы данных с поставщиком LINQ. Я думаю, что это единственная причина, почему вы так часто видите примеры реализации шаблонов репозиториев с IQueryable. Это не врожденное ограничение, накладываемое EF на POCO.
(Вот как я об этом думаю, не будучи экспертом в шаблонах проектирования, поэтому приветствуются тяжелые атаки и исправления в комментариях.)