tl;博士
在一个好的设计中。是否应该在单独的业务逻辑层(在 asp.net MVC 模型中)处理访问数据库,还是可以将IQueryable
s 或DbContext
对象传递给控制器?
为什么?各自的优缺点是什么?
我正在用 C# 构建一个 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's static for simplicity here, in fact it's 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
代替静态构建方法并更改 Kittens 的类。基本上它应该是数据库实体之上的一层,因此控制器不必知道实际的数据库、映射器或实体框架。
- 每种设计有哪些优缺点?
- 有明确的赢家吗?为什么?
注意:当然,替代方法作为答案也非常有价值。
澄清1:这在实践中并不是一个简单的应用。这是一个包含数十个控制器和数千行代码的应用程序,实体不仅在这里使用,还用于其他数十个 C# 项目。这里的例子是一个简化的测试用例。