静态辛格尔顿在ASP.Net会话 [英] Static Singleton In ASP.Net Session

查看:124
本文介绍了静态辛格尔顿在ASP.Net会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读有关在ASP.Net单身人士和我见过的各种实现和建议。我试过这个后我实现模型:<一href=\"http://stackoverflow.com/questions/2134511/asp-net-singleton\">http://stackoverflow.com/...asp-net-singleton

下面是我的问题:我想我正在实例化将持续当前会话生命的对象,但不会话之间共享。例如,如果两个用户同时登录,我想让他们一个全局对象的每一个自己的一个实例。下面是我的实现。这是做正确的方法?

 公共类AppGlobal
{
    #区域Contructors    公共AppGlobal(){}    公共静态AppGlobal实例
    {
        得到
        {
            HttpSessionState会话= HttpContext.Current.Session;            如果(会话[AppGlobalInstance] == NULL)
            {
                会议[AppGlobalInstance] =新AppGlobal();
            }            返回(AppGlobal)会议[AppGlobalInstance];
        }
    }    #endregion    #地区的公共属性    公共用户UserObject {搞定;组; }
    公共活动CampaignObject {搞定;组; }
    公开名单&LT; INT&GT; SelectedContactIDs =新的List&LT; INT&GT;();
    公开名单&LT; INT&GT; UnsubmittedContactIDs =新的List&LT; INT&GT;();
    公开名单&LT; INT&GT; SubmittedContactIDs =新的List&LT; INT&GT;();
    公开名单&LT; INT&GT; ProcessedContactIDs =新的List&LT; INT&GT;();    #endregion    #地区的公共实例方法    公共无效ClearCampaign()
    {
        CampaignObject = NULL;
        UnsubmittedContactIDs.Clear();
        SubmittedContactIDs.Clear();
        ProcessedContactIDs.Clear();
        SelectedContactIDs.Clear();
    }
    公共无效LoadCampaign(INT CAMPAIGNID)
    {
        //确保旧数据被覆盖
        MailCampaignManagerEntities DB =新MailCampaignManagerEntities();        db.Campaigns.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges;        //清除活动和相关数据
        ClearCampaign();        //在AppGlobal设置活动对象
        this.CampaignObject = db.Campaigns.SingleOrDefaultasp.net(X =&GT; x.CampaignID == CAMPAIGNID);        //填充联系状态列表
        this.UnsubmittedContactIDs.AddRange(从this.CampaignObject.CampaignContacts点¯x
                                                 其中,x.ContactSubmissionID == NULL
                                                 选择x.CampaignContactID);        this.SubmittedContactIDs.AddRange(从this.CampaignObject.CampaignContacts点¯x
                                               其中,x.ContactSubmissionID!= NULL
                                               选择x.CampaignContactID);        this.ProcessedContactIDs.AddRange(从this.CampaignObject.CampaignContacts点¯x
                                               其中,x.ContactSubmissionID!= NULL
                                               &功放;&安培; x.ContactSubmission.DateProcessed!= NULL
                                               选择x.CampaignContactID);
    }    #endregion    #地区的公共静态方法    公共静态无效WriteLogEntry(INT?CAMPAIGNID,诠释?contactSubmissionID,诠释?scheduledDropID,诠释?userid,字符串activityDescription)
    {
        ActivityLog activityLog =新ActivityLog();
        activityLog.CampaignID = CAMPAIGNID;
        activityLog.ContactSubmissionID = contactSubmissionID;
        activityLog.ScheduledDropID = scheduledDropID;
        activityLog.UserID =用户ID;
        activityLog.Text = activityDescription;
        activityLog.CreatedDate = DateTime.Now;        使用(MailCampaignManagerEntities DB =新MailCampaignManagerEntities())
        {
            db.ActivityLogs.AddObject(activityLog);
            db.SaveChanges();
        }
    }    #endregion
}


解决方案

的实施通常应该是还行,但...

您应该将对象标记 [Serializable接口] ,具体取决于您所配置的SessionStateModule。 Web场或Web园通常使用模块比是InProc 之一等,他们使用序列来存储会话状态。否则,它看起来好你的对象序列化,所以有没有问题。

您可能要检查是否有任何当前届全部,或者你可以得到一个的NullReferenceException 。这将可能意味着但是错误配置的应用程序,或者在生命周期太早打电话。

您因为您在您检查并设置会话变量的方式来比赛状态的应用程序可能在单个会话两次分配一个AppGlobal对象。我不认为即使是目前的一个问题,但它的东西要记住,如果你想加入更多花哨的东西。以prevent它,你可以使用锁定是这样的:

 公共类AppGlobal
{
   私人静态对象_syncRoot =新的对象();   公共静态AppGlobal实例
   {
       得到
       {
           HttpSessionState会话= HttpContext.Current.Session;           锁定(_syncRoot)
           {
               如果(会话[AppGlobalInstance] == NULL)
               {
                   会议[AppGlobalInstance] =新AppGlobal();
               }
           }           返回(AppGlobal)会议[AppGlobalInstance];
       }
    }
}

如果你想存储禁止序列化对象里的任何东西,你需要支持其他SessionStateModules,你可以存储你的情况是采用了经典的单例模式(的这里是一个很好的实现)。 ConcurrentDictionary 可能会是一个很好的一个。作为重点,你可以使用独特之处在于您做的事情存储在会话中,像一个GUID。您将需要从集合中删除该条目时,会以任何方式结束。

I've been reading about singletons in ASP.Net and I've seen various implementations and suggestions. I've tried to model my implementation after this one: http://stackoverflow.com/...asp-net-singleton

Here is my question: I would like the object that I'm instantiating to last the life of the current session, but not be shared between sessions. For example, if two users are logged in at the same time, I want them to each "own" an instance of a global object. Below is my implementation. Is this the proper way to do this?

public class AppGlobal
{
    #region Contructors

    public AppGlobal() { }

    public static AppGlobal Instance
    {
        get
        {
            HttpSessionState session = HttpContext.Current.Session;

            if (session["AppGlobalInstance"] == null)
            {
                session["AppGlobalInstance"] = new AppGlobal();
            }

            return (AppGlobal)session["AppGlobalInstance"];
        }
    }

    #endregion

    #region Public Properties

    public User UserObject { get; set; }
    public Campaign CampaignObject { get; set; }
    public List<int> SelectedContactIDs = new List<int>();
    public List<int> UnsubmittedContactIDs = new List<int>();
    public List<int> SubmittedContactIDs = new List<int>();
    public List<int> ProcessedContactIDs = new List<int>();

    #endregion

    #region Public Instance Methods

    public void ClearCampaign()
    {
        CampaignObject = null;
        UnsubmittedContactIDs.Clear();
        SubmittedContactIDs.Clear();
        ProcessedContactIDs.Clear();
        SelectedContactIDs.Clear();
    }
    public void LoadCampaign(int campaignID)
    {
        //Ensure that old data is overwritten
        MailCampaignManagerEntities db = new MailCampaignManagerEntities();

        db.Campaigns.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges;

        //Clear the campaign and associated data
        ClearCampaign();

        //Set campaign object in AppGlobal
        this.CampaignObject = db.Campaigns.SingleOrDefaultasp.net(x => x.CampaignID == campaignID);

        //Populate Contact Status Lists
        this.UnsubmittedContactIDs.AddRange(from x in this.CampaignObject.CampaignContacts
                                                 where x.ContactSubmissionID == null
                                                 select x.CampaignContactID);

        this.SubmittedContactIDs.AddRange(from x in this.CampaignObject.CampaignContacts
                                               where x.ContactSubmissionID != null
                                               select x.CampaignContactID);

        this.ProcessedContactIDs.AddRange(from x in this.CampaignObject.CampaignContacts
                                               where x.ContactSubmissionID != null
                                               && x.ContactSubmission.DateProcessed != null
                                               select x.CampaignContactID);
    }

    #endregion

    #region Public Static Methods

    public static void WriteLogEntry(int? campaignID, int? contactSubmissionID, int? scheduledDropID, int? userID, string activityDescription)
    {
        ActivityLog activityLog = new ActivityLog();
        activityLog.CampaignID = campaignID;
        activityLog.ContactSubmissionID = contactSubmissionID;
        activityLog.ScheduledDropID = scheduledDropID;
        activityLog.UserID = userID;
        activityLog.Text = activityDescription;
        activityLog.CreatedDate = DateTime.Now;

        using (MailCampaignManagerEntities db = new MailCampaignManagerEntities())
        {
            db.ActivityLogs.AddObject(activityLog);
            db.SaveChanges();
        }
    }

    #endregion
}

解决方案

The implementation should usually be "okay", but...

You should mark the object as [Serializable], depending on the SessionStateModule that you have configured. Web farms or a web gardens typically use modules other than the InProc one, and they use serialization to store the session state. Otherwise, it looks okay for your object to be serialized, so no problems there.

You may want to check if there is currently any session at all, or you could get a NullReferenceException. That would probably mean a misconfigured application however, or a call too early in the life cycle.

Your application might allocate an AppGlobal object twice for a single session due to a race condition that you have in the way you check and set the Session variable. I don't think even that is currently an issue, but it's something to keep in mind if you want to include more fancy stuff. To prevent it, you can use lock like this:

public class AppGlobal
{
   private static object _syncRoot = new object();

   public static AppGlobal Instance
   {
       get
       {
           HttpSessionState session = HttpContext.Current.Session;

           lock (_syncRoot)
           {
               if (session["AppGlobalInstance"] == null)
               {
                   session["AppGlobalInstance"] = new AppGlobal();
               }
           }

           return (AppGlobal)session["AppGlobalInstance"];
       }
    }     
}

If you ever want to store anything inside the object that prohibits serialization, and you need to support other SessionStateModules, you could store your instances in a collection that uses a classic Singleton pattern (here is a good implementation). ConcurrentDictionary would probably be a good one. As the key, you could use something unique that you do store in your Session, like a GUID. You would need to remove the entry from the collection when the session ends in any way.

这篇关于静态辛格尔顿在ASP.Net会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆