[英]ASP.NET MVC guidelines for static classes for database access
The way I am utilising the MVC pattern at the moment in my ASP.NET application (using Entity Framework) is as follows: 我在ASP.NET应用程序(使用Entity Framework)中使用MVC模式的方式如下:
1) My Models
folder contains all EF entities, as well as my ViewModels 1)My
Models
文件夹包含所有EF实体以及我的ViewModel
2) I have a Helpers
folders where I store classes created for the purposes of the particular application. 2)我有一个
Helpers
文件夹,我存储为特定应用程序创建的类。
3) In my Helpers
folder, I have a static class named MyHelper
which contains methods that access the DB using EF. 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();
}
}
}
}
4) My controllers then call these functions where necessary: 4)我的控制器然后在必要时调用这些函数:
namespace myApp.Controllers
{
public class ProductController : Controller
{
[HttpGet]
public async Task<ActionResult> Index(int productId)
{
var productVM = await MyHelper.GetProductAsync(productId);
return View(productVM);
}
}
}
I usually encounter comments in SO of the type "don't use a static class, static classes are evil, etc". 我经常在SO中遇到“不使用静态类,静态类是邪恶等”类型的注释。 Would this apply in such a scenario?
这适用于这种情况吗? If yes, why?
如果是,为什么? Is there a better 'structure' my app should follow for best practices and for avoiding such pitfalls?
是否有更好的“结构”我的应用程序应遵循最佳实践并避免此类陷阱?
You can't really use a static class for this. 你不能真正使用静态类。 Your Entity Framework context should have one and only one instance per request.
您的实体框架上下文应该每个请求只有一个实例。 Your methods here instantiate a new context for each method, which is going to cause a ton of problems with Entity Framework.
您的方法在这里为每个方法实例化一个新的上下文,这将导致Entity Framework出现大量问题。
The general concept is fine, but your MyHelper
class should be a normal class. 一般概念很好,但你的
MyHelper
类应该是普通的类。 Add a constructor that takes an instance of your context, and then use a DI container to inject the context into the helper class and the helper class into your controller. 添加一个构造函数,该构造函数接受上下文的实例,然后使用DI容器将上下文注入到辅助类中,将辅助类注入控制器中。
UPDATE UPDATE
Helper 帮手
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();
}
}
}
Controller 调节器
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);
}
}
}
Then, you just need to set up a DI container to inject everything. 然后,您只需要设置一个DI容器来注入所有东西。 The code for that is entirely dependent on which container you end up going with, so I can't really help you further.
该代码完全取决于您最终使用的容器,因此我无法真正帮助您。 It's usually pretty straight-forward, though.
不过,这通常很简单。 Just read the docs for the container.
只需阅读容器的文档即可。 You'll want to set the life-time scope of your objects to the request.
您需要将对象的生命周期范围设置为请求。 Again, it's different for different containers, but they'll all have some sort of request-scope.
同样,它对于不同的容器是不同的,但它们都有某种请求范围。
I was thinking to add comment to ChrisPratt's answer, but it ended being too long, so let me add separate answer. 我想在ChrisPratt的答案中添加评论,但结尾太长了,所以让我添加单独的答案。
Basically, this is not a life/death choice. 基本上,这不是生死攸关的选择。 Sure, static methods are not as flexible as classes for db access.
当然,静态方法不像db访问类那样灵活。 But they are not bad per-se.
但它们本身并不坏 。 One DbContext per request is a something to aim for .
每个请求一个DbContext是一个目标 。 It is not an absolute must.
这不是绝对必须的。 It is kinda like dependency injection - you get more flexibility and in turn increase code complexity.
它有点像依赖注入 - 你获得更多的灵活性,反过来又增加了代码的复杂性。
Look at these three questions and their answers, by taking into account everything they say, I'm sure you'll be able to answer your question yourself: 看看这三个问题及其答案,考虑到他们所说的一切,我相信你能够自己回答你的问题:
EDIT: Chris left good comment on my answer and I've changed answer a bit to take into account what he said. 编辑:克里斯对我的回答留下了很好的评论,我已经改变了一点回答,考虑到他说的话。
Your idea is correct and I use it always. 你的想法是正确的,我总是使用它。 But the style is like this: 1) For each entity (ie User) we have a static class inside Providers folder.
但风格是这样的:1)对于每个实体(即用户),我们在Providers文件夹中有一个静态类。 In this class we can do general methods (ie create, Get, GetAll , ..)
在这个类中我们可以做一般方法(即create,Get,GetAll,..)
public static class Users
{
public static IEnumerable<kernel_Users> GetAll()
{
Kernel_Context db = new Kernel_Context();
return db.kernel_Users;
}
public static kernel_Users Get(int userId)
{
Kernel_Context db = new Kernel_Context();
return db.kernel_Users.Where(c => c.UserId == userId).FirstOrDefault();
}
...
}
2) We have another class that is not static.It is inside Models folder. 2)我们有另一个不是静态的类。它在Models文件夹中。 This is the place that we can access to an instance of the entity :
这是我们可以访问实体实例的地方:
public partial class kernel_Users
{
[Key]
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
[NotMapped]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public bool Delete(out string msg)
{
...
}
...
} }
I use a static class that has the context injected into a static constructor for the purposes of loading a cache of data that rarely changes. 我使用一个静态类,它将上下文注入到静态构造函数中,以便加载很少更改的数据缓存。 And it (should) be thread safe.
它(应该)是线程安全的。 I hope this helps you, it's very handy in my experience:
我希望这会对你有所帮助,这在我的经历中非常方便:
public static class StaticCache<T> where T: class
{
private static List<T> dbSet;
public static Dictionary<string, List<T>> cache = new Dictionary<string, List<T>>();
private static readonly object Lock = new object();
public static void Load(DbContext db, string connStr, string tableName)
{
lock (Lock)
{
try
{
if (connStr != null)
{
using (db)
{
dbSet = db.Set<T>().ToList();
cache.Add(tableName, dbSet);
}
}
}
catch { }
}
}
}
void Testit()
{
var context = new YourContextSubClass(connStr);
StaticCache<TableEntity>.Load(context, connstr, "tableEntityNameString");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.