C#(MVC3)中静态(扩展)类中动态属性的行为是什么
本文关键字:是什么 属性 扩展 MVC3 静态 动态 | 更新日期: 2023-09-27 18:22:01
我是.NET和C#开发的新手,但我是一名长期的开发人员,使用C、C++、Java、PHP等。
我有一个用于引用数据库的数据模型的MVC3扩展类。它在类中被设置为"私有静态",但我认为它跟不上数据库的更改。换句话说,当我更改控制器中的数据时,这些更改在数据库中不会被"注意到",因为它是静态的。目前,我正在为每次使用创建和处理变量,以进行补偿。
我的问题是:
- 静态db变量可能会有这种行为,我说得对吗
- 是否有必要处理静态类中的动态变量,或者垃圾回收仍会自动处理它
以下是该类的相关片段:
namespace PBA.Models {
using System;
using System.Text.RegularExpressions;
using PBA.Models;
using PBA.Controllers;
public static class Extensions {
private static PbaDbEntities db = null;
public static PbaDbEntities GetDb() {
// TODO: find out about static memory/disposal, etc.
//
if (db != null) {
db.Dispose();
}
db = new PbaDbEntities();
return db;
}
public static string GetCheckpointState(this Activity activity, long memberProjectId) {
GetDb(); // TODO: Do I need to do this each time, or will a one-time setting work?
string state = CheckpointController.CHECKPOINT_STATUS_NOT_STARTED;
try {
var sub = db.ActivitySubmissions.
Where(s => s.activityId == activity.activityId).
Where(s => s.memberProjectId == memberProjectId).
OrderByDescending(s => s.submitted).
First();
if (sub != null) {
state = sub.checkpointStatusId;
}
}
catch (Exception e) {
// omitted for brevity
}
return state;
}
}
}
您的代码在生产中会严重失败
DataContext不是线程安全的;不能在请求之间共享上下文。
在多线程应用程序中,永远不要将可变对象放在静态字段中。
这样忽略异常是个糟糕的主意,如果你不想处理异常,就不要尝试/catch或catch&重新思考。这样想吧,在你埋葬了异常之后,你的程序处于无效状态,b/c是你无法控制的错误。现在,b/c您已经埋葬了异常,您的程序可以继续运行,但它的状态不好。
如果你的代码能够投入生产,3.5年后,一些jr.程序员会卷入一些半夜的风暴,因为突然之间网站坏了,尽管它以前可以工作。完全不可能追踪异常发生的地方,所以,这个可怜的家伙将连续48小时在各处添加日志代码来追踪问题。他会发现某个DBA决定将MemberProjectId列重命名为MemberProjectIdentifier,这导致您的linq崩溃。
想想孩子们,处理例外情况,不要埋葬他们。
顺便说一句,是的,我一直是那种必须找出这些错误的人。
在编写代码之前,您似乎需要阅读有关mvc3和实体框架的内容,并在这里寻求有关充满不良实践的代码的帮助。
回答您的问题:
1-无
2-作为1 的答案毫无意义
做对了,这里有一些有用的文档:http://msdn.microsoft.com/en-us/library/ie/gg416514(v=vs.98).aspx
编辑:添加一些显式修复
您可以从一个静态类访问您的dbcontext,类似于以下内容:
var context = DbProvider.CurrentDb;
这个想法是始终从这里访问数据库:从扩展方法和控制器操作。
然后,DbProvider.CurrentDb的实现将是这样的:
public static classDbProvider {
public static void Initialize(){
HttpContext.Current.ApplicationInstance.BeginRequest += CreateDb;
HttpConetxt.Current.ApplicationInstance.EndRequest += DisposeDb;
}
private static void CreateDb(object sender, EventArgs e) {
HttpContext.Items.Add("CurrentDb", new PbaDbEntities(););
}
private static void DisposeDb(object sender, EventArgs e)
{
Current.Dispose();
HttpContext.Items.Remove("CurrentDb");
}
public static PbaDbEntities CurrentDb{
get {
return (PbaDbEntities)HttpContext.Current.Items["CurrentDb"];
}
}
}
正如您所看到的,它将为每个请求创建一个新的Db,并且它将仅在该请求中可用。这样,您的数据库将在每个请求结束时被处理。这种模式被称为"在视图中打开会话"。
最后,您需要初始化调用方法的DbProvider
事件Application_start中的Global.asax文件中的Initialize()
。
希望能有所帮助。
我对这里的上下文一无所知——如果db只是一个类似连接的对象,但它似乎是在丢弃和重新创建不必要的东西。
最好创建一个属性(无论你做什么),以便保持一致。
private static Thing _thing;
private static Thing thing{
get{
if(_thing==null){
_thing=new Thing();
}
return _thing;
}
}