Locks only occur when a session is accessed by the same user from multiple threads.
SessionId | A unique string label not generated by us. This random number, encoded into a string composed of Latin letters and numbers, reaches a maximum of 24 characters in length. |
Created | Time to create a session. |
Expires | The time when the session expires. |
Lookdate | The moment when the session was blocked. |
Lookid | Session lock number. |
Looked | Is there currently a lock. |
Itemcontent | The contents of the session in serialized form. |
Userid | The user Id to which the session belongs (my guest has id = 1) |
CREATE TABLE [dbo].[Sessions] ( [SessionId] varchar(24) COLLATE Cyrillic_General_CI_AS NOT NULL, [Created] smalldatetime NOT NULL, [Expires] smalldatetime NOT NULL, [LockDate] smalldatetime NOT NULL, [LockId] int NOT NULL, [Locked] bit CONSTRAINT [DF_Sessions_Locked] DEFAULT 0 NOT NULL, [ItemContent] varbinary(max) NULL, [UserId] int NOT NULL, CONSTRAINT [PK_Sessions] PRIMARY KEY CLUSTERED ([SessionId]) ) ON [PRIMARY] GO
using QueryHunter.WebDomain.Layouts.Session; public class SessionStateProvider : SessionStateStoreProviderBase { // ... }
/// <summary> /// . /// </summary> public class SessionStateProvider : SessionStateStoreProviderBase { CommonEntities _dataContext; int _timeout; /// <summary> /// , , ... /// </summary> public override void Initialize(string name, NameValueCollection config) { if (config == null) throw new ArgumentNullException("config"); base.Initialize(name, config); var applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath; var configuration = WebConfigurationManager.OpenWebConfiguration(applicationName); var configSection = (SessionStateSection)configuration.GetSection("system.web/sessionState"); _timeout = (int)configSection.Timeout.TotalMinutes; // , EntityFramework . // Dependency Injection . _dataContext = new CommonEntities(); } public override void Dispose() { _dataContext.Dispose(); } /// <summary> /// " " . /// </summary> public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return GetSessionItem(context, id, false, out locked, out lockAge, out lockId, out actions); } /// <summary> /// . /// </summary> public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return GetSessionItem(context, id, true, out locked, out lockAge, out lockId, out actions); } /// <summary> /// . /// GetItem, GetItemExclusive. /// </summary> private SessionStateStoreData GetSessionItem(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { locked = false; lockAge = new TimeSpan(); lockId = null; actions = 0; var sessionItem = _dataContext.DbSessions.Find(id); // if (sessionItem == null) return null; // , if (sessionItem.Locked) { locked = true; lockAge = DateTime.UtcNow - sessionItem.LockDate; lockId = sessionItem.LockId; return null; } // , if (DateTime.UtcNow > sessionItem.Expires) { _dataContext.Entry(sessionItem).State = EntityState.Deleted; _dataContext.SaveChanges(); return null; } // , . if (exclusive) { sessionItem.LockId += 1; sessionItem.Locked = true; sessionItem.LockDate = DateTime.UtcNow; _dataContext.SaveChanges(); } locked = exclusive; lockAge = DateTime.UtcNow - sessionItem.LockDate; lockId = sessionItem.LockId; var data = (sessionItem.ItemContent == null) ? CreateNewStoreData(context, _timeout) : Deserialize(context, sessionItem.ItemContent, _timeout); data.Items["UserId"] = sessionItem.UserId; return data; } /// <summary> /// , . /// </summary> public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { var sessionItem = _dataContext.DbSessions.Find(id); if (sessionItem.LockId != (int)lockId) return; sessionItem.Locked = false; sessionItem.Expires = DateTime.UtcNow.AddMinutes(_timeout); _dataContext.SaveChanges(); } /// <summary> /// . /// </summary> public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { var intLockId = lockId == null ? 0 : (int)lockId; var userId = (int)item.Items["UserId"]; var data = ((SessionStateItemCollection)item.Items); data.Remove("UserId"); // var itemContent = Serialize(data); // , . if (newItem) { var session = new DbSession { SessionId = id, UserId = userId, Created = DateTime.UtcNow, Expires = DateTime.UtcNow.AddMinutes(_timeout), LockDate = DateTime.UtcNow, Locked = false, ItemContent = itemContent, LockId = 0, }; _dataContext.DbSessions.Add(session); _dataContext.SaveChanges(); return; } // , , // . var state = _dataContext.DbSessions.Find(id); if (state.LockId == (int)lockId) { state.UserId = userId; state.ItemContent = itemContent; state.Expires = DateTime.UtcNow.AddMinutes(_timeout); state.Locked = false; _dataContext.SaveChanges(); } } /// <summary> /// . /// </summary> public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { var state = _dataContext.DbSessions.Find(id); if (state.LockId != (int)lockId) return; _dataContext.Entry(state).State = EntityState.Deleted; _dataContext.SaveChanges(); } /// <summary> /// . /// </summary> public override void ResetItemTimeout(HttpContext context, string id) { var sessionItem = _dataContext.DbSessions.Find(id); if (sessionItem == null) return; sessionItem.Expires = DateTime.UtcNow.AddMinutes(_timeout); _dataContext.SaveChanges(); } /// <summary> /// , . /// , . /// </summary> public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) { var data = new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout); data.Items["UserId"] = 1; return data; } /// <summary> /// . /// </summary> public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { var session = new DbSession { SessionId = id, UserId = 1, Created = DateTime.UtcNow, Expires = DateTime.UtcNow.AddMinutes(timeout), LockDate = DateTime.UtcNow, Locked = false, ItemContent = null, LockId = 0, }; _dataContext.DbSessions.Add(session); _dataContext.SaveChanges(); } #region public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return false; } public override void EndRequest(HttpContext context) { } public override void InitializeRequest(HttpContext context) { } #endregion #region private byte[] Serialize(SessionStateItemCollection items) { var ms = new MemoryStream(); var writer = new BinaryWriter(ms); if (items != null) items.Serialize(writer); writer.Close(); return ms.ToArray(); } private SessionStateStoreData Deserialize(HttpContext context, Byte[] serializedItems, int timeout) { var ms = new MemoryStream(serializedItems); var sessionItems = new SessionStateItemCollection(); if (ms.Length > 0) { var reader = new BinaryReader(ms); sessionItems = SessionStateItemCollection.Deserialize(reader); } return new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), timeout); } #endregion }
namespace CustomSessionStateProvider.Controllers { public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { return View(); } // public ActionResult SetToSession() { Session["Foo"] = new List<int>() {1, 2, 3, 4, 5}; Session["Boo"] = new SomeClass(50); return View(); } // public ActionResult ViewSession() { return View(); } } // . [Serializable] public class SomeClass { readonly int _value; public SomeClass(int value) { _value = value; } public override string ToString() { return "value = " + _value.ToString(); } } }
Source: https://habr.com/ru/post/141056/
All Articles