C#(MVC3)中静态(扩展)类中动态属性的行为是什么 我是在.NET和C语言开发的新手,但一直是一个长期开发人员,用C、C++、java、PHP等。
我的数据模型有一个MVC3扩展类,它引用数据库。它在类中被设置为“private static”,但我认为它不能跟上数据库的变化。换句话说,当我更改控制器中的数据时,这些更改在数据库中不会被“注意”,因为它是静态的。目前,我正在为每次使用创建和处理变量,以进行补偿 我的问题是:C#(MVC3)中静态(扩展)类中动态属性的行为是什么 我是在.NET和C语言开发的新手,但一直是一个长期开发人员,用C、C++、java、PHP等。,c#,asp.net-mvc-3,entity-framework,static,C#,Asp.net Mvc 3,Entity Framework,Static,我的数据模型有一个MVC3扩展类,它引用数据库。它在类中被设置为“private static”,但我认为它不能跟上数据库的变化。换句话说,当我更改控制器中的数据时,这些更改在数据库中不会被“注意”,因为它是静态的。目前,我正在为每次使用创建和处理变量,以进行补偿 我的问题是: 静态db变量的这种行为正确吗 是否有必要在静态类中处理动态变量,或者垃圾收集仍然会自动处理它 以下是该类的相关片段: namespace PBA.Models { using System; using
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;
}
}
}
您的代码将在生产中严重失败。
数据上下文不是线程安全的;您不能在请求之间共享上下文
在多线程应用程序中,切勿将可变对象放在静态字段中。您的代码将在生产中严重失败。
数据上下文不是线程安全的;您不能在请求之间共享上下文
在多线程应用程序中,永远不要将可变对象放在静态字段中。以这种方式忽略异常是个糟糕的主意,如果您不想处理异常,请不要尝试/catch或catch&rethrow。这样考虑一下,在您掩埋了异常之后,您的程序处于无效状态,b/c一些您无法控制的错误被排除。现在,b/c您已经隐藏了异常,您的程序可以继续运行,但它处于一个糟糕的状态 如果你的代码能够投入生产,3.5年后,一些jr程序员会卷入半夜的风暴,因为网站突然被破坏了,即使它曾经工作过。追踪异常发生的位置是完全不可能的,因此,这个可怜的家伙将连续48小时在各地添加日志代码来追踪问题。他会发现某处的DBA决定将列MemberProjectId重命名为MemberProjectIdentifier,这导致linq崩溃 想想孩子,处理例外,不要埋葬他们
顺便说一句,是的,我就是那个必须找出这些类型错误的人。以这种方式忽略异常是个糟糕的主意,如果你不想处理异常,就不要尝试/catch,或者catch&rethrow。这样考虑一下,在您掩埋了异常之后,您的程序处于无效状态,b/c一些您无法控制的错误被排除。现在,b/c您已经隐藏了异常,您的程序可以继续运行,但它处于一个糟糕的状态 如果你的代码能够投入生产,3.5年后,一些jr程序员会卷入半夜的风暴,因为网站突然被破坏了,即使它曾经工作过。追踪异常发生的位置是完全不可能的,因此,这个可怜的家伙将连续48小时在各地添加日志代码来追踪问题。他会发现某处的DBA决定将列MemberProjectId重命名为MemberProjectIdentifier,这导致linq崩溃 想想孩子,处理例外,不要埋葬他们
顺便说一句,是的,我就是那个必须找出这些类型错误的人。在编写代码之前,您似乎需要先阅读有关mvc3和实体框架的内容,并在这里寻求有关编码中充满错误做法的帮助 回答您的问题: 1-否 2-作为1的答案毫无意义 正确操作,以下是一些有用的文档: 编辑:添加一些显式修复 您可以从静态类访问dbcontext,如下所示:
var context = 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"];
}
}
}
其思想是始终从这里访问数据库:从扩展方法和控制器操作
然后,DbProvider.CurrentDb的实现如下:
var context = 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
Initialize()
在您的Global.asax文件中,在事件应用程序启动时
希望能有所帮助。在编写代码之前,您似乎需要先阅读有关mvc3和实体框架的内容,并在这里寻求有关编写了大量错误实践的帮助 回答您的问题: 1-否 2-作为1的答案毫无意义 正确操作,以下是一些有用的文档: 编辑:添加一些显式修复 您可以从静态类访问dbcontext,如下所示:
var context = 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"];
}
}
}
其思想是始终从这里访问数据库:从扩展方法和控制器操作
然后,DbProvider.CurrentDb的实现如下:
var context = 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
Initialize()
在您的Global.asax文件中,在事件应用程序启动时
希望它能有所帮助。我对这里的上下文没有任何概念——如果db只是一个类似于对象的连接,或者不是,但是看起来您正在丢弃并重新创建任何不必要的东西 最好创建一个属性(无论你做什么),以便保持一致
private static Thing _thing;
private static Thing thing{
get{
if(_thing==null){
_thing=new Thing();
}
return _thing;
}
}
我不知道这里的上下文——如果db只是一个连接,比如