TL;DR
В хорошем дизайне. Должен ли доступ к базе данных обрабатываться на отдельном уровне бизнес-логики (в модели MVC asp.net) или нормально ли передавать объекты IQueryable
или DbContext
на контроллер?
Почему? Каковы плюсы и минусы каждого?
Я создаю приложение ASP.NET MVC на С#. Он использует EntityFramework как ORM.
Немного упростите этот сценарий.
У меня есть таблица базы данных с симпатичными пушистыми котятами. У каждого котенка есть ссылка на изображение котенка, индекс пушистого котенка, имя котенка и котенок id. Они сопоставляются с EF, созданным POCO, называемым Kitten
. Я мог бы использовать этот класс в других проектах, а не только в проекте asp.net MVC.
У меня есть KittenController
, который должен забрать последних пушистых котят в /Kittens
. Он может содержать некоторую логику выбора котенка, но не слишком много логики. Я спорил с другом о том, как реализовать это, я не буду раскрывать стороны:)
Вариант 1: db в контроллере:
public ActionResult Kittens() // some parameters might be here
{
using(var db = new KittenEntities()){ // db can also be injected,
var result = db.Kittens // this explicit query is here
.Where(kitten=>kitten.fluffiness > 10)
.Select(kitten=>new {
Name=kitten.name,
Url=kitten.imageUrl
}).Take(10);
return Json(result,JsonRequestBehavior.AllowGet);
}
}
Вариант 2: отдельная модель
public class Kitten{
public string Name {get; set; }
public string Url {get; set; }
private Kitten(){
_fluffiness = fluffinessIndex;
}
public static IEnumerable<Kitten> GetLatestKittens(int fluffinessIndex=10){
using(var db = new KittenEntities()){ //connection can also be injected
return db.Kittens.Where(kitten=>kitten.fluffiness > 10)
.Select(entity=>new Kitten(entity.name,entity.imageUrl))
.Take(10).ToList();
}
} // it static for simplicity here, in fact it probably also an object method
// Also, in practice it might be a service in a services directory creating the
// Objects and fetching them from the DB, and just the kitten MVC _type_ here
}
//----Then the controller:
public ActionResult Kittens() // some parameters might be here
{
return Json(Kittens.GetLatestKittens(10),JsonRequestBehavior.AllowGet);
}
Примечания: GetLatestKittens
вряд ли будет использоваться в другом месте кода, но может. Можно использовать конструктор Kitten
вместо статического метода построения и изменения класса для котят. В основном это должен быть слой над объектами базы данных, поэтому диспетчеру не нужно знать реальную базу данных, карту или структуру сущности.
- Каковы некоторые плюсы и минусы для каждого дизайна?
- Есть ли явный победитель? Почему?
Примечание. Конечно, альтернативные подходы очень ценятся как ответы.
Разъяснение 1: На практике это не тривиальное применение. Это приложение с десятками контроллеров и тысячами строк кода, и сущности не только используются здесь, но и десятки других проектов С#. Примером здесь является уменьшенный тестовый пример.