This might be a silly question but i was wondering if it would be a good idea to delete all expired "sessions" from my database, every 15 minutes?
Or just leave it there? Session expires after X minutes, its no longer useful anymore, seems like it just taking up space?
When my team deploys SQL Server session state in a .NET application, we simply create a job with SQL Server Agent to clean up the expired sessions nightly (or at some appropriate interval).
Unless you have massive amounts of traffic, you can do this whenever it is convenient without worrying about instantly deleting unused sessions, but it's definitely a good idea to clean up.
If you're using the standard SQL Server Session State, old sessions are automatically deleted for you. Until the old entries are deleted, sessions do not expire, since the provider does not actively monitor the Expires column in the session table.
The install / configuration utility creates a SQL Agent job that calls the DeleteExpiredSessions stored procedure every 60 seconds. This means that SQL Agent needs to be running for session expiration to work and for the table to get cleaned up.
If your table looks like that
SessionId datatype,
SessionLastTouch datetime
then when registering the new session do some cleanup after writing(session issue or touch) to the table, like this:
delete from YourSessionsRegister WHERE SessionLastTouch < DATEADD(min, -15, GETDATE())
BUT
May be better way is to cleanup the session register based on some schedule - to reduce DB load in peak hours - simply create the job, which cleans up the register every night or smth. like this
Related
IDE: Visual Studio, C# .net 4.0, Winforms application
Is there any way in SQL Server to implement a column in a table which can set itself automatically to 0 when it has not received any ACK (acknowledgement) signal from the application side?
The requirement is I want to keep a column which can keep track that Is application is open or it has been closed?
One way to implement is using the OnClose() event, i.e. on Close() I can change it's value to 0. but the problem is suppose application got hanged for some reason or Power is gone than the value in database will not be updated to zero.
So I want to create an automated column which can track this situation and make itself zero when the application is not sending any request or idle means closed.
please suggest how to handle this.
You can't do that. The only thing you can do is to save GETDATE() in a column in a table as the last activity time of the application and invoke the stored procedure from a high-priority thread every 10 seconds for example.
When you want to know if the application is alive or not, just check this value, if more than 10 seconds is passed since then, you app is gone.
UPDATE:
A more precise but complex approach would be to listen on a socket inside your application and then whenever you want to know if the application is alive, send a request from your sql script to PING the application. You should use CLR programming for this approach, but I think the first one will be practically enough.
Considering it will be a multiple instance scenario where multiple instances of the application can point to same database. You can try the following:
Create a separate table to maintain sessions. This table would contain three columns 1)Machine name or IP 2) Session Id (GUID) and 3) TimeStamp.
Whenever application starts create a new session id and make an entry into this table it means new session is started.
Keep on updating timestamp on every request based on session id.
Have a timeout configured somewhere in web.config or database which will come in handy later.
Now when application is exiting gracefully then delete the row from the table.
Now if application crashes the row won't be delete so next time when application starts you can check if the row already exists. Use machine name or IP to query to the table.
Use the timeout setting configured in (3) above to determine since how long the application is idle.
I have developed an Asp.Net MVC Web Application and deployed it on IIS 8 Server and in my application I am using a list to store online users and display them in a page using the following code
if (HttpRuntime.Cache["LoggedInUsers"] != null)
{
List<string> loggedInUsers = (List<string>)HttpRuntime.Cache["LoggedInUsers"];
if (loggedInUsers.Contains(model.UserName))
{
}
else
{
loggedInUsers.Add(model.UserName);
HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
}
}
For some reason, the list gets cleared every night and when I look for the active users, I see it empty.
Is it something that has to be dealt on IIS 8 or is there any better way to implement the Online users using a database table may be..
IIS can recycle your application pool (for several reasons, including idling and no requests, too much memory use, etc...) At that point your application will be unloaded, and then loaded again later. Hence your cache values are gone.
Second, do you have any code that at some point prunes and removes old entries from cache? If not, it means you got a memory leak as it'll continue to grow indefinitely (and thereby trigger application pool recycle).
If you do have prunning code (so the cache is actively managed to avoid indefinite growth), and you need its contents to survive past pool restarts, then you have few options:
Use database. Simply have a table of active users and add/delete there.
Pro: survives even unexpected crashes of app, iis, and even machine itself.
Con: Slow due to db access and db contention point possibilities.
Put code in your application start / end event handlers to serialize contents to a file on end, and deserialize on start.
Pro: faster than db. works during graceful shutdowns.
Con: will not work due to unexpected crash.
Your site probably shuts down after a certain amount of time when there is no activity. Look at IIS settings for Application Pools (more specifically "Set idle-timeout to never in IIS") on google...
I build web-site and want to count clicks on some button. I create and try this class of counter:
public static class Counter
{
public static int counter = 0;
}
Every time I click on the button the counter is increament (counter++) ans I see it in my site, But, if I close the chrome and enter again to my site the counter starts from zero.
How can I save the counter? "Static" dont need to do that?
My bet is that it happens because the application space is flushed - it shouldn't reset just because you closed your browser window, thus abandoning the current session (if the session cookie isn't persistent, that is.)
Visual Studio may republish your files (if using a remote IIS) or just plainly restart a local IIS Express instance, depending on how you set your development environment; I do believe setting a specific content as Static would cause it to be available to all current sessions.
That said, you may want to keep it under the current session (using the Session object).
Optionally, if you want to persist information in between server restarts, you may try reading and writing to a local storage, such as a plaintext or XML file. You can find a very nice article about this on the following link:
http://www.codeproject.com/Articles/544839/Implement-ASP-NET-custom-XML-file-configuration
A more sophisticated version would use a local (or remote) database, for example.
Hope it works for you.
static fields are unique per-process. Depending on your application pool configuration, you could have 2, 20 or 100 copies of that.
They're also not thread safe. There are very, very few instances (pun) where a static member is appropriate.
Just off the top of my head, a particular "instance" of a static will disappear when:
The application pool is recycled. On IIS, this defaults to 20 minutes of inactivity.
The application process exits (you may have multiple processes running within your app pool). This happens as part of (1), but will also happen if, say, you're using the Visual Studio debug web server (Cassini), have your project configured to launch the site for debugging, and close the browser that was launched initially. (This happens because VS considers closing the browser that it launched equivalent to saying "I'm done playing. Back to coding now," or hitting the stop button.)
Another thread overwrites the value you've stored (google "race condition.")
You really, really should be storing this in a database. If you're building a website, you need a database anyway. ANYTHING related to application state should be stored in the database.
ALSO, this really, really shouldn't be happening server-side. Are you really performing a postback every time someone clicks anywhere on a page? If so, you have JavaScript in place to handle that, so just skip this insanity, have said script fire off an AJAX request, and have the target handler log it in the database.
Looks like your using a web site so presuming ASP.net. There are a number of ways to store the information. Database could be one or a persistent cookie could be the way to do it. See this article on how to create cookies: How do I set/unset cookie with jQuery?
You can try save it in session and then it will stay until the session is time out(20 minutes) if you want it to long time just write it to file in known location and when you close the web write the value to the file and when the web is up again take the vakue from the file.
In my database on my SQL Server I have a table with users. This table have a column named logged_on which is a bit, either true or false. When someone log on the column will be true, else false. If something ever happens when someone is using my wpf-application, like the power disappears and the application couldn't log out the user this column will be true and the user will not be able to login again, because the application will tell this user that he is already logged on. Is there something i could do to avoid this situation? On the server-side or in the application?
Any sugestions are appreciated :)
I think you'll need a "LastActive" date-time stamp. Then run a scheduled job that says "if you've been inactive for X minutes, change the state of the logged_on flag".
Are you trying to insure that only one login can be active at the same time? Is that the end game?
Sounds like you need to change the approach a little, perhaps tracking last interaction date/time (every time the WPF app calls SQL) and enforcing a session timeout limit instead. You could use that DateTime to automatically log out anyone that hasn't interacted with the server in several minutes by checking it in addition to the *logged_on* bit field (always switching *logged_on* to false if the DateTime is too stale).
Is there an important reason you can't just throw away the old login in situations where the user logs in again without logging out first?
I would like my ASP.NET MVC app to execute a query once per day. What is the recommended way to do this?
My first thought is to put a timer in Global.asax that goes off every 24 hours, then call my query from the Elapsed handler. Any pitfalls with doing it this way? Is there a better way?
Edit
Let me add a little detail to what I'm trying to do. I'd specifically like the query to execute at midnight every day. If a day is missed (say due to sever maintenance or upgrading the app), that wouldn't be a major issue.
Edit 2
Couple more details:
The query is actually an INSERT, not a SELECT. The purpose is to add a "renewal" record for any member that is due to renew his/her membership at the end of the month.
I'm using SQL Server Compact (it's a very small database).
Does it have to originate in the Web layer? Who'd be there to consume the HTML? Typically, periodic SQL queries are scheduled within the database. In case of MS SQL Server - via the SQL Agent job facility. SQL Server can even send e-mail.
RE: edit2: Should've told so right away. SQL Server Compact is not the same as SQL Server - for one, it does not have SQL Agent IIRC. Still, invoking the Web layer is an overkill. I'd use a Windows Scripting Host file (.js) in conjuction with Windows task scheduler. WSH files can connect to databases via ADO and do whatever they want - inserts, selects, anything.
To detect missed scheduled runs, introduce an extra table with a log of scheduled runs. Then on subsequent runs you can analyse the date of the last run and act accordingly.
Edit2: so no administrative access. You should really tell all those details in the question. In this case, I would go through the Web layer after all, but the scheduling would be on MY end - where I do have control. Have Task Scheduler run on your end and invoke an HTTP URL on the server. To invoke URLs, you can use something like the free CURL utility. Running IE in scheduled manner has the disadvantage of leaving the window open.
IIS is not a scheduling engine.
Edit3 re:comment: sorry, I've misunderstood the nature of your setup. My own experiences have clouded my judgement :) Can you just run a check during every logon operation, and if it's been a while since the last maintenance operation, run it right then and there? How long does the maintenance take? If it's ~1min+, makes sense to run it in a worker thread, so that the logging-on user is not made wait.
Scheduling daily maintenance is a good idea in general, and it is implemented fairly often, but it seems you simply don't have the capability.
I do this very thing in my web apps, but use Asynchronous HTTP Handlers (http://msdn.microsoft.com/en-us/library/ms227433.aspx#Y512); I believe this would be recommended. I just start it off on application start and shut it down on application end (Global.asx).
The thing to remember is that you'll probably have to store the last time the query ran in the database because you'll loose track of that when your application pool recycles.
I'm doing this by putting some fake information in "Cache" and put the time period i want then handel the "_onCacheRemove" event do whatever i wanna do then recreate the "CacheItem" again:
e.g.
I put my tasks in Enum with the time that i wanna to rerun this task in seconds:
public enum ScheduledTasks
{
CleanGameRequests = 120,
CleanUpOnlineUsers = 6
}
then deal with them at "Application_Start" :
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
// Adding the tasks i want at App_Start
// so if the application restarted my task will refreshed.
AddTask(ScheduledTasks.CleanGameRequests);
AddTask(ScheduledTasks.CleanUpOnlineUsers);
}
// event to handel
private static CacheItemRemovedCallback _onCacheRemove;
private void AddTask(ScheduledTasks task)
{
_onCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(task.ToString(), (int)task, null,
DateTime.Now.AddSeconds((int)task), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, _onCacheRemove);
}
public void CacheItemRemoved(string key, object time, CacheItemRemovedReason r)
{
var task = (ScheduledTasks)Enum.Parse(typeof(ScheduledTasks), key);
switch (task)
{
case ScheduledTasks.CleanGameRequests:
// Do the concept that you wanna to do.
GameRequest.CleanUp();
break;
case ScheduledTasks.CleanUpOnlineUsers:
OnlineUsers.CleanUp();
break;
default:
break;
}
// Don't forget to recreate the "CacheItem" again.
AddTask(task);
}
Note: You may make your time management as you want. In my case i
wanna these tasks to run every period
of time regardless of what time it is.
In your case you should check the time
before then recreate the CacheItem
again.
Hope this helped :)
Unless you have very active site chances are that IIS will bring your application down and there will be no process to execute your task.
Alternatives:
just do that during/immediately after request that is close enough by time
have external task that will trigger the operation on your site via GET/POST.
reconfigure IIS to never recycle/stop your app pool. Than your timer has chance to execute.
use some external service on the server to schedule the task ("at" or even SQL tasks).