我在ASP.NET应用程序(使用Entity Framework)中使用MVC模式的方式如下:
1)My Models文件夹包含所有EF实体以及我的viewmodel
2)我有一个Helpers文件夹,我存储为特定应用程序创建的类.
3)在我的Helpers文件夹中,我有一个名为MyHelper的静态类,它包含使用EF访问数据库的方法.
- namespace myApp.Helpers
- {
- public static class MyHelper
- {
- public static async Task<ProductVM> GetProductAsync(int productId)
- {
- using (var context = new myEntities())
- {
- return await context.vwxProducts.Where(x => x.ProductId == productId).Select(x => new ProductVM { A = x.A,B = x.B }).FirstOrDefaultAsync();
- }
- }
- }
- }
- namespace myApp.Controllers
- {
- public class ProductController : Controller
- {
- [HttpGet]
- public async Task<ActionResult> Index(int productId)
- {
- var productVM = await MyHelper.GetProductAsync(productId);
- return View(productVM);
- }
- }
- }
我经常在SO中遇到“不使用静态类,静态类是邪恶等”类型的注释.这适用于这种情况吗?如果是,为什么?是否有更好的“结构”我的应用程序应遵循最佳实践并避免此类陷阱?
解决方法
你不能真正使用静态类.您的实体框架上下文应该每个请求只有一个实例.您的方法在这里为每个方法实例化一个新的上下文,这将导致Entity Framework出现大量问题.
一般概念很好,但你的MyHelper类应该是普通的类.添加一个构造函数,该构造函数接受上下文的实例,然后使用DI容器将上下文注入到辅助类中,将辅助类注入控制器中.
UPDATE
帮手
- namespace myApp.Helpers
- {
- public class MyHelper
- {
- private readonly DbContext context;
- public MyHelper(DbContext context)
- {
- this.context = context;
- }
- public async Task<ProductVM> GetProductAsync(int productId)
- {
- return await context.vwxProducts.Where(x => x.ProductId == productId).Select(x => new ProductVM { A = x.A,B = x.B }).FirstOrDefaultAsync();
- }
- }
- }
调节器
- namespace myApp.Controllers
- {
- public class ProductController : Controller
- {
- private readonly MyHelper myHelper;
- public ProductController(MyHelper myHelper)
- {
- this.myHelper = myHelper;
- }
- [HttpGet]
- public async Task<ActionResult> Index(int productId)
- {
- var productVM = await myHelper.GetProductAsync(productId);
- return View(productVM);
- }
- }
- }
然后,您只需要设置一个DI容器来注入所有东西.该代码完全取决于您最终使用的容器,因此我无法真正帮助您.不过,这通常很简单.只需阅读容器的文档即可.您需要将对象的生命周期范围设置为请求.同样,它对于不同的容器是不同的,但它们都有某种请求范围.