MVC EF 数据库存储库模式
MVC EF database repository pattern
我已经阅读了关于这个主题的各种帖子,但找不到我的问题的答案。
普遍的共识是我应该为 1 个工作单元(比如 1 个网页)创建上下文。我在我的 Database.cs(见下文)中用 'using' 封装了每个方法,因此对我来说 - 这意味着每次调用此 class 中的方法 - 都会创建一个上下文。因此,如果我要从 HomeController.cs 中的同一操作调用 Database.cs 的 2 个方法 - 这是否意味着创建了 2 个上下文?
像这样在 Database.cs 中声明一个私有字段不是更好吗:
private Entities db = new Entities()
Database.cs class 中的每个方法都可以访问它吗?哪种方法最好?
我当前的实现(我只打算包括验证方法,但数据库中有很多方法 class):
HomeController.cs
[AllowAnonymous]
public class HomeController : Controller
{
private IDatabase Database;
public HomeController()
{
this.Database = new Database();
}
[HttpGet]
public ActionResult Verify(string id)
{
if (Database.VerifyUser(id))
{
return View();
}
else
{
ViewBag.Error = "There was an error with the verification process";
return View();
}
}
}
Database.cs
public class Database : IDatabase
{
... some other methods ...
public bool VerifyUser(string verificationHash)
{
using (Entities db = new Entities())
{
var userToVerify = db.VerifyUser(verificationHash);
int count = userToVerify.Count();
if (count == 1)
{
return true;
}
else
{
return false;
}
}
}
}
db.VerifyUser(..) - 这是对存储过程的调用
是的,这意味着有两个 DbContext 实例。
更好的办法是在您的数据库中拥有一个 DbContext 实例 class 并在您的所有方法中使用该实例。
public class Database : IDatabase, IDisposeable
{
private Entities db;
public Database()
{
db = new Entities()
}
... some other methods ...
public bool VerifyUser(string verificationHash)
{
var userToVerify = db.VerifyUser(verificationHash);
int count = userToVerify.Count();
if (count == 1)
{
return true;
}
else
{
return false;
}
}
public void Dispose()
{
db.Dispose()
}
}
然后,当您从数据库实例完成后,您将处置它,它将处置 DbContext
public class HomeController : Controller
{
private IDatabase Database;
public HomeController()
{
this.Database = new Database();
}
[HttpGet]
public ActionResult Verify(string id)
{
using(this.Database)
{
if (Database.VerifyUser(id))
{
return View();
}
else
{
ViewBag.Error = "There was an error with the verification process";
return View();
}
}
}
}
顺便说一句:您可能更愿意在控制器级别处理您的资源。在这种情况下,您不需要在操作中添加 using 语句
例如将此添加到您的控制器:
protected override void Dispose(bool disposing)
{
this.Database.Dispose();
base.Dispose(disposing);
}
是的,在您的设计中,DbContext 在每个方法调用中创建和处理。
其实把所有的数据库操作都放到一个class上,一遍又一遍的创建DbContext并不是一个好的解决方案。您将来可能会遇到 class 的问题。它可能及时有数百个方法,因此很难维护,并且所有实体在语义上彼此不相关,因此可能会造成混淆。我认为将实体类型分离为 classes 是更好的解决方案。例如,您有一个用户、项目、部门。如果我们将我的解决方案应用于这些实体,那么 uml class 图将是这样的。
所有存储库都引用 DbContext。它被称为依赖注入。这意味着 dbcontext 被实例化一次并通过必要的存储库传递其引用,因此没有上下文 re-creation。还有一个通用存储库,您可以在其中放置标准程序。
因此您可以像这样使用存储库。
[HttpGet]
public ActionResult Verify(string id){
using(var context = new DbContext())
{
var userRepo = new UserRepository(context);
//Department repository can be used over the same context.
var departmentRepo = new DepartmentRepository(context);
if(userRepo.verifyUser(id)){
return View();
}
}
}
我已经阅读了关于这个主题的各种帖子,但找不到我的问题的答案。
普遍的共识是我应该为 1 个工作单元(比如 1 个网页)创建上下文。我在我的 Database.cs(见下文)中用 'using' 封装了每个方法,因此对我来说 - 这意味着每次调用此 class 中的方法 - 都会创建一个上下文。因此,如果我要从 HomeController.cs 中的同一操作调用 Database.cs 的 2 个方法 - 这是否意味着创建了 2 个上下文?
像这样在 Database.cs 中声明一个私有字段不是更好吗:
private Entities db = new Entities()
Database.cs class 中的每个方法都可以访问它吗?哪种方法最好?
我当前的实现(我只打算包括验证方法,但数据库中有很多方法 class):
HomeController.cs
[AllowAnonymous]
public class HomeController : Controller
{
private IDatabase Database;
public HomeController()
{
this.Database = new Database();
}
[HttpGet]
public ActionResult Verify(string id)
{
if (Database.VerifyUser(id))
{
return View();
}
else
{
ViewBag.Error = "There was an error with the verification process";
return View();
}
}
}
Database.cs
public class Database : IDatabase
{
... some other methods ...
public bool VerifyUser(string verificationHash)
{
using (Entities db = new Entities())
{
var userToVerify = db.VerifyUser(verificationHash);
int count = userToVerify.Count();
if (count == 1)
{
return true;
}
else
{
return false;
}
}
}
}
db.VerifyUser(..) - 这是对存储过程的调用
是的,这意味着有两个 DbContext 实例。 更好的办法是在您的数据库中拥有一个 DbContext 实例 class 并在您的所有方法中使用该实例。
public class Database : IDatabase, IDisposeable
{
private Entities db;
public Database()
{
db = new Entities()
}
... some other methods ...
public bool VerifyUser(string verificationHash)
{
var userToVerify = db.VerifyUser(verificationHash);
int count = userToVerify.Count();
if (count == 1)
{
return true;
}
else
{
return false;
}
}
public void Dispose()
{
db.Dispose()
}
}
然后,当您从数据库实例完成后,您将处置它,它将处置 DbContext
public class HomeController : Controller
{
private IDatabase Database;
public HomeController()
{
this.Database = new Database();
}
[HttpGet]
public ActionResult Verify(string id)
{
using(this.Database)
{
if (Database.VerifyUser(id))
{
return View();
}
else
{
ViewBag.Error = "There was an error with the verification process";
return View();
}
}
}
}
顺便说一句:您可能更愿意在控制器级别处理您的资源。在这种情况下,您不需要在操作中添加 using 语句 例如将此添加到您的控制器:
protected override void Dispose(bool disposing)
{
this.Database.Dispose();
base.Dispose(disposing);
}
是的,在您的设计中,DbContext 在每个方法调用中创建和处理。
其实把所有的数据库操作都放到一个class上,一遍又一遍的创建DbContext并不是一个好的解决方案。您将来可能会遇到 class 的问题。它可能及时有数百个方法,因此很难维护,并且所有实体在语义上彼此不相关,因此可能会造成混淆。我认为将实体类型分离为 classes 是更好的解决方案。例如,您有一个用户、项目、部门。如果我们将我的解决方案应用于这些实体,那么 uml class 图将是这样的。
所有存储库都引用 DbContext。它被称为依赖注入。这意味着 dbcontext 被实例化一次并通过必要的存储库传递其引用,因此没有上下文 re-creation。还有一个通用存储库,您可以在其中放置标准程序。
因此您可以像这样使用存储库。
[HttpGet]
public ActionResult Verify(string id){
using(var context = new DbContext())
{
var userRepo = new UserRepository(context);
//Department repository can be used over the same context.
var departmentRepo = new DepartmentRepository(context);
if(userRepo.verifyUser(id)){
return View();
}
}
}