Asp.net static object appears sometimes as non global - asp.net

I have an android application as client and ASP.Net + ADO.Net hosted on GoDaddy server. The asp.net has static data structure which stores (among other) the android locations, this data structure is persist also to SQL server 2008 data base. each time the android client change position it send its location to the server which update the data structure and data base. each time the applicaton start the data structure is filled according to the persist data from the data base.
The Problems : altough the data structure is static thus should be global it looks like sometimes there are more then one instances of this static data structure.
Is anyone aware of this issue ?
How can i prevent this from hapening ?
Nathan

This object is has actually a dictionary with name as key and info as
value. This object is updated according to android client which access
the asp.net via HTTP thorugh aspx Page_Load :
HttpContext.Current.Application.Lock() .
The first error is that you use that kind of lock and not the correct one.
The Application.Lock() and Application.Unlock() are designed as lock mechanism only for the Application variables.
To correct lock your static Dictionary you need to use the lock(){} as:
private static readonly object syncLock = new object();
public static Dictionary<int, int> DictMem = new Dictionary<int, int>();
... inside some function....
lock (syncLock)
{
// actions with your dictionary
DictMem[2]=3;
}
Also I like to tell you that the static is not guaranty that you have only one on your program. If the provider use web garden you have more than one, and when the pool recycles then you loose them.

Related

Optimize connection to SQLite DB using EF Core in UWP app

I'm currently working on a C# UWP application that runs on Windows 10 IoT Core OS on an ARM processor. For this application, I am using a SQLite DB for my persistence, with Entity Framework Core as my ORM.
I have created my own DBContext and call the Migrate function on startup which creates my DB. I can also successfully create a DBContext instance in my main logic which can successfully read/write data using the model. All good so far.
However, I've noticed that the performance of creating a DbContext for each interaction with the DB is painfully slow. Although I can guarantee that only my application is accessing the database (I'm running on custom hardware with a controlled software environment), I do have multiple threads in my application that need to access the database via the DbContext.
I need to find a way to optimize the connection to my SQLite DB in a way that is thread safe in my application. As I mentioned before, I don't have to worry about any external applications.
At first, I tried to create a SqliteConnection object externally and then pass it in to each DbContext that I create:
_connection = new SqliteConnection(#"Data Source=main.db");
... and then make that available to my DbContext and use in in the OnConfiguring override:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(_connection);
}
... and then use the DbContext in my application like this:
using (var db = new MyDbContext())
{
var data = new MyData { Timestamp = DateTime.UtcNow, Data = "123" };
db.MyData.Add(data);
db.SaveChanges();
}
// Example data read
MyDataListView.ItemsSource = db.MyData.ToList();
Taking the above approach, I noticed that the connection is closed down automatically when the DbContext is disposed, regardless of the fact that the connection was created externally. So this ends up throwing an exception the second time I create a DbContext with the connection.
Secondly, I tried to create a single DbContext once statically and share it across my entire application. So instead of creating the DbContext in a using statement as above, I tried the following:
// Where Context property returns a singleton instance of MyDbContext
var db = MyDbContextFactory.Context;
var data = new MyData { Timestamp = DateTime.UtcNow, Data = "123" };
db.MyData.Add(data);
db.SaveChanges();
This offers me the performance improvements I hoped for but I quickly realized that this is not thread safe and wider reading has confirmed that I shouldn't do this.
So does anyone have any advice on how to improve the performance when accessing SQLite DB in my case with EF Core and a multi-threaded UWP application? Many thanks in advance.
Secondly, I tried to create a single DbContext once statically and share it across my entire application. So instead of creating the DbContext in a using statement as above, I tried the following...This offers me the performance improvements I hoped for but I quickly realized that this is not thread safe and wider reading has confirmed that I shouldn't do this.
I don't know why we shouldn't do this. Maybe you can share something about what you read. But I think, you can make the DBContext object global and static and when you want to do CRUD, you can do it in main thread like this:
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
//App.BloggingDB is the static global DBContext defined in App class
var blog = new Blog { Url = NewBlogUrl.Text };
App.BloggingDB.Add(blog);
App.BloggingDB.SaveChanges();
});
But do dispose the DBContext at a proper time as it won't automatically get disposed.

Create Database If Not Exist Without Restarting Application

I am creating dynamic connection strings in my project. They're created on the fly with the information provided specifically for every user. When the application first fires off, if a database doesn't exist (first time user logs on), a new database is created without problems with this initializer:
public DataContext() : base()
{
// ProxyCreation and LazyLoading doesn't affect the situation so
// comments may be removed
//this.Configuration.LazyLoadingEnabled = false;
//this.Configuration.ProxyCreationEnabled = false;
string conStr = GetDb();
this.Database.Connection.ConnectionString = conStr;
}
The problem is, with this method, I have to restart the application pool on the server and the new user should be the first accessor to the application.
I need the same thing without a requirement of restarting the app. Is that possible?
(This is a SPA using AngularJS on MVC views and WebApi as data provider - May be relevant somehow, so thought I should mention)
I already tried this, but this creates an error for EF and the application doesn't start at all...
You could try a little bit different approach to connect directly (and create) the right database.
public class DataContext : DbContext
{
public DataContext(DbConnection connection) : base(connection, true) { }
}
Here you create the DbContext already with the right connection.
Take also care because you need to specify to migrations that the right connection should be used (not the Web.Config connection but the connection that raised the database creation).
See the second overload here https://msdn.microsoft.com/en-US/library/hh829099(v=vs.113).aspx#M:System.Data.Entity.MigrateDatabaseToLatestVersion.

does onDisconnect event on SignalR2 releases all of its resources upon disconnect?

I have a concurrent dictionary List on my controller that stores list of online users. For example when Client A and Client B connects there are 2 online clients present on the list, but when i disconnect B and then re- connect again it must still show 2 online clients but in my case, only Client B detected as online user(disconnected then reconnected). I am using IIS server 7.5.. Please help me with this, do i need to use a database rather than dictionary? I think it resets the dictionary to zero if one user disconnects and reconnects again.... :( Below is my hub class code
public class Chat : Hub
{
//add online client
private static ConcurrentDictionary<string, string> personLists
= new ConcurrentDictionary<string, string>();
public void Connect(string Username, int ID)
{
string id = Context.ConnectionId;
if (!personLists.ContainsKey(Username))
{
personLists.TryAdd(Username, id);
Clients.Caller.viewOnlinePersons(personLists.Where(p => p.Key != Username));
Clients.Others.enters(Username);
}
else
{
string notif = "user: "+Username+" is already used";
Clients.Caller.onUse(notif);
}
The concurrent dictionary should work just fine. It'd be good if you could post some code, but if you go this route with concurrent dictionary, make sure it's static (the Hub classes get created and destroyed per signal) and I think it'd be better suited placed on the hub itself and private (and of course static, again). You can also use Dependency Injection with SignalR which will be a lot cleaner.
You'll only need database as a backplane if you plan on running the application on multiple servers where of course a memory of a single server is not accessible by the other servers and a duplicate dictionary would be created for each server, so in that case you need to take the storage and move it up a bit in the architecture to be accessible by all the servers.

fetching and updating data from web service

Data can be fetched into an application through web service can it be possible to update data in web service from our application ..
In general a Web Service implementation can be any arbitrary code, so insert/update/delete is nothing special.
I suspect that there's something behind your question, some specific issue in mind? You may want to explain why you think there's a problem.
Of course create a web method that takes parameters and then save the data as required
[WebMethod]
public bool UpdateData(string firstName, string lastName, int id)
{
// do some data access code here
}
Then use in your code in a similar way as to when your are acquiring data from the web service:
MyWebServiceClient client = new MyWebServiceClient();
bool updated = client.UpdateData("Jon", "Skeet", 1);

ASP.NET Connection String

I am having some trouble with one of my ASP.NET 2.0 application's connection string. There are instances that I would get a ConnectionString Property Has not Been Initialized problem which occurs randomly and intermittently and without any reason.
My Connection string is actually coming from a webservice, because different kinds of users are provided with different sets of connection string depending on their user level.
What I have done so far goes like this:
I have a master page (mstr.page) and the corresponding code behind (mstr.page.vb).
In my master page, I retrieve initially the connection string and store the same into a session variable, i.e.
Session("ConnString") = "RetrievedConnectionString"
Now in one of my pages, let us say page1.aspx.vb, I use public shared functions from a class (named MyClass.vb) and use it in my page1.aspx.vb.
Some codes for reference:
[MyClass.vb]
Imports System.Web
NameSpace ClassNameSpace
Public Class Admin
Protected Shared da as New DataAccess()
Public Shared Function MYFunction() as String
'Execute some sql statements here, using the DataAccess
stringToReturn = Ctype(da.ExecuteScalar("SQLCommand"), String)
Return stringToReturn
End Function
End Class
End NameSpace
[DataAccessClass.vb]
Public Class DataAccess()
Private m_ConStr As String = ""
Public Sub New()
m_ConStr = HttpContext.Current.Session("ConnString")
End Sub
'Some methods for SQL statement execution (ExecuteQuery, ExecuteScalar)
End Class
[Page1.aspx.vb]
Imports ClassNameSpace
Protected Sub Page_Load(....) Handles Me.Load
Dim strValue as String = Admin.MyFunction()
End Sub
I have placed the code above to show you some rough idea of how things are going.
Basically, the function Admin.MyFunction() at times fails, because in the data access class, the connection string seems to have lost it's value (either blank or Nothing).
This has troubled me for quite some time already.
I hope someone can point me in the right direction to resolve this. Basically, I want my connection string which is retrieved by each user visiting the web application be maintained across all the time and be used anywhere. Session variable does not seem to be the best fit since when the ASP.NET recycles its process, the session is lost.
By the way, I am retrieving the connectionstring initially via the master page from a web service. I tried to place the same retrieve function in the Data Access class when conditions is that the session variable is lost, but I think my application cannot connect to the Web Service during the recycle process.
Any advice would be greatly appreciated on this.
Update on this:
I tried to use Session Variable and set the mode to State Server, but apparently some DLLs which I am using cannot be serialized, thus I am back to square one.
Is there a better way to do this?
One thing to check is if your Session is getting clobbered. If your using the (default) in-memory Session, then sessions die anytime an ASP.NET worker process is recycled. If this is causing your issue, you might have to look into using the ASP.NET SessionServer in IIS, or SQL Server as your Session storage.
I'd try to limit your use of the Session for this type of thing as much as possible. If you utilize the Web.Config for storing your connection strings, you can access it at anytime and it will not expire on you like the session.
You may also consider having a static data access class if it is the same for all users for the applications instance...
This is the exact same problem I was experiencing, and it turned out to be the session variables dying so the connection string couldn't be initialized properly.
Why cant your app use just one connection string? and why does the connection string need to come in through a webservice? that adds a huge amount of latency to the entire process. I assume it probably has to do something with data security in your database.
If you have to do this, I'd say, can't you have a fall back / default connectionstring? Wrap your code that attempts to pull it out of the session with some error handeling and if it fails revert to your default?
I would place your web service and web app in different app pools. Then increase the timeout length of your web apps pool.

Resources