Платформа проекта инфраструктуры .NET Entity (архитектура)
Я пытаюсь определить, как лучше всего архитектор проекта .NET Entity Framework достичь хорошего многоуровневого подхода. Пока я пробовал это в игре, основанной на просмотре, где игроки владеют и управляют планетами. Вот как у меня это получилось:
Веб-сайт
Здесь содержится весь внешний интерфейс.
Проект С# - MLS.Game.Datastrong >
Это содержит файл EDMX со всеми моими сопоставлениями данных. Здесь не намного больше.
Проект С# - MLS.Game.Business
Здесь содержатся различные классы, которые я называю "Менеджеры", такие как PlanetManager.cs. Менеджер планет имеет различные статические методы, которые используются для взаимодействия с планетой, такие как getPlanet (int planetID), которые возвращают сгенерированный объект кода из MLS.Game.Data.
На веб-сайте я сделаю что-то вроде этого:
var planet = PlanetManager.getPlanet(1);
Он возвращает объект Planet из MLS.Game.Data(сгенерированный из EDMX). Он работает, но это меня беспокоит, потому что это означает, что мой передний конец должен ссылаться на MLS.Game.Data. Я всегда чувствовал, что GUI должен только ссылаться на бизнес-проект.
Кроме того, я обнаружил, что мои классы менеджера, как правило, очень тяжелые. Я получаю в них десятки статических методов.
Итак... мой вопрос: как все остальные выкладывают проекты ASP EF?
ИЗМЕНИТЬ
После еще нескольких, есть дополнительные предметы, которые меня беспокоят. Например, допустим, у меня есть объект Planet, который снова генерирует код из мастера. Что, если пришло время, чтобы моя Планета нуждалась в специализированном свойстве, скажем, "Население", которое является вычислением какого-то типа, основанного на других свойствах объекта Planet. Хочу ли я создать новый класс, который наследует от Планеты, а затем вернет это? (хм, интересно, закрыты ли эти классы EF?)
Спасибо
Ответы
Ответ 1
Вы можете попробовать следующее, чтобы улучшить ситуацию:
- Используйте EF для извлечения DTO в вашем слое данных, а затем используйте эти DTO для заполнения более богатых бизнес-объектов на уровне вашего бизнеса. Ваш пользовательский интерфейс только тогда должен будет ссылаться на бизнес-уровень.
- Как только вы создали богатые бизнес-объекты, вы можете начать интернализировать часть логики из классов менеджера, эффективно очищая бизнес-уровень.
Я лично предпочитаю более богатую модель над моделью менеджера, потому что, как вы говорите, вы получаете нагрузку статических методов, которые неизбежно заканчиваются цепями внутри других статических методов. Я считаю это слишком грязным и, что более важно, сложнее понять и гарантировать согласованность ваших объектов в любой момент времени.
Если вы инкапсулируете логику внутри самого класса, вы можете быть более уверенным в состоянии своего объекта независимо от характера внешнего вызывающего.
Хороший вопрос, кстати.
Ответ 2
ИМХО, ваш текущий макет в порядке. Совершенно нормально, когда ваш пользовательский интерфейс ссылается на слой "Данные", когда вы его вызываете. Я думаю, что, возможно, ваша озабоченность возникает из-за терминологии. "Данные", которые вы описали чаще всего, называются слоем "бизнес-объекты" (BOL). Тогда общий макет должен иметь уровень бизнес-логики (BLL), который является вашим уровнем "Менеджеры" и уровнем доступа к данным (DAL). В вашем сценарии LINQ to Entites (предположим, что вы его используете) является вашим DAL. Обычным эталонным шаблоном будет: -
UI ссылки BLL и BOL.
BLL refences BOL и DAL (LINQ to Entites).
Посмотрите эту серию статей для более подробной информации.
Ответ 3
Что касается вашего второго вопроса (после EDIT), если вам нужно или хотите добавить функции в объекты EF, вы можете использовать частичные классы. Щелкните правой кнопкой мыши файл EDMX и выберите код просмотра.
Или, если этого недостаточно, вы можете сорвать конструктор и написать свои собственные классы с поддержкой EF.
Здесь (краткое) обсуждение обоих вариантов -
http://msdn.microsoft.com/en-us/library/bb738612.aspx
Ответ 4
Что касается вашего второго вопроса в разделе "EDIT":
Если я не ошибаюсь, классы, созданные EF, не запечатаны, и они являются PARTIAL-классами, поэтому вы можете легко расширить их, не касаясь самих сгенерированных файлов.
Сгенерированный класс будет:
public partial class Planet : global::System.Data.Objects.DataClasses.EntityObject
{
...
}
чтобы вы могли легко создать свой собственный "PlanetAddons.cs" (или все, что вы хотите назвать), чтобы расширить этот класс:
public partial class Planet
{
property int Population {get; set;}
...
}
Довольно аккуратный, а? Не нужно выводить и создавать иерархии искусственных объектов....
Марк
Ответ 5
Я не эксперт, но это звучит очень хорошо для меня. Это похоже на то, что у меня есть в моих решениях, за исключением того, что я просто объединяю проект EF с бизнес-проектом. Мои решения не такие большие, и мои объекты не требуют много разума, поэтому для меня это хорошо. У меня тоже есть много разных методов для каждого из моих статических вспомогательных классов.
Если вы не хотите, чтобы уровень представления знал о слое доступа к данным, вам нужно создать несколько промежуточных классов, что, вероятно, будет большой работой. Итак, в чем проблема с вашей текущей настройкой?
Ответ 6
Ваш макет выглядит нормально.
Я бы добавил слой Utility/Common
Веб-интерфейс
Бизнес-уровень
DataObjects
Утилиты
Ответ 7
Я бы добавил DTO на ваш бизнес-уровень, который является представлением "немой объект" (т.е. только свойствами) объектов в вашем слое данных. Затем ваши классы "Менеджер" могут вернуть их, например:
class PlanetManager
{
public static PlanetDTO GetPlanet(int id) { // ... }
}
и ваш пользовательский интерфейс может обрабатывать только BLL-уровень через POCOs; Менеджер (то, что я бы назвал классом "Mapper" ) обрабатывал весь перевод между объектами и слоем данных. Также, если вам нужно расширить класс, вы можете иметь "виртуальное" свойство на объекте DTO и перевести менеджера на его компоненты обратно.