我在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容器来注入所有东西.该代码完全取决于您最终使用的容器,因此我无法真正帮助您.不过,这通常很简单.只需阅读容器的文档即可.您需要将对象的生命周期范围设置为请求.同样,它对于不同的容器是不同的,但它们都有某种请求范围.