Если Entity Framework предназначен для работы с POCO, то почему зависимость от IObjectSet? - PullRequest
1 голос
/ 04 августа 2010

Я продолжаю слышать об EF 4.0, POCO, IObjectSet, UnitOfWork (кстати, UoW, по крайней мере, больше 17 лет, когда я впервые услышал это) и т. Д.

Так что некоторые люди говорят о «шаблоне» репозитория. и т. д. Есть множество блогеров, демонстрирующих свою придуманную «обертку» или репозиторий или что-то подобное. Но все они требуют, чтобы IObjectSets (или в некоторых случаях - IQueryables) зависали от их POCO. Похоже, что вы можете писать запросы против них.

Так что если нужен IObjectSet, а не просто IList или какой-то другой более простой набор, почему мы говорим, что это POCO и не содержит EF?

Если я хочу поменять EF снизу, мне нужно убедиться, что мой «другой» O / R Mapper (я знаю, я знаю, что EF - не просто O / R Mapper) понимает IObjectSet и может анализировать ExpressionTrees из запросов выполняют и в остальном ведут себя подобно EF.

Ответы [ 4 ]

2 голосов
/ 04 августа 2010

IObjectSet - это не интерфейс, который делает POCO Entity, это просто контейнер персистентности IObjectSet. Смысл POCO состоит в том, чтобы предотвратить получение производных классов модели от типа EF, который обеспечивает шаблон TOC POCO в EF4.

Шаблон репозитория - это необязательный дополнительный уровень абстракции от вашего ORM, позволяющий упростить реализацию другого в случае необходимости. Разделение интересов и т. Д. И т. Д.

1 голос
/ 04 августа 2010

В ответ на фразу: «Если я хочу поменять EF из-под»:

В моем бизнесе более вероятно, что я бы поменял базу данных, скажем, с Oracle на SQL Server (илинаоборот), чем я бы поменял каркас доступа к данным.С другой стороны, существуют варианты, которые делают EF благоприятным выбором.

Существуют другие поставщики LINQ, помимо предоставляемых EF (например, LLBLGen).Конечно, поменять уровень данных EF для NHibernate или EasyObjects будет сложно, потому что платформы не имеют достаточной четности функций, чтобы облегчить переход;однако LINQ был разработан для того, чтобы другие провайдеры LINQ могли вступить и предложить свое собственное решение.

1 голос
/ 04 августа 2010
0 голосов
/ 05 августа 2010

Ваш вопрос содержит неверное утверждение: верно то, что 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.

(Вот как я об этом думаю, не будучи экспертом в шаблонах проектирования, поэтому приветствуются тяжелые атаки и исправления в комментариях.)

...