How can I open database connection at runtime? - asp.net

I am working on ASP.Net MVC project. I am making my database transactions with;
using (ISession session = FluentNHibernateHelper.OpenSession())
{
var user = session.Query<User>()
.FirstOrDefault(x => x.UserEmail == email && x.UserPassword == password); }
Instead of using this type of code block which is like open-close connection everytime, I want to open connection at runtime and I want to use that session variable everywhere. Maybe some codes in Application_Start()in Global.asax.cs?
I am open to your valuable ideas. Thank you for your help!

It's poor practice to leave a connection open nor maintain the state in the ORM across multiple transactions as state issues can crop up rather quickly as you make multiple requests against the same object & connection.
However, if you must, you could inject it as a Singleton service which would live longer than a single request. This is problematic for scaling and not recommended.
services.AddSingleton<ISession>(provider =>
{
return FluentNHibernateHelper.OpenSession()
});
More information: What is the difference between services.AddTransient, service.AddScoped and service.AddSingleton methods in ASP.NET Core?

Related

Is it possible to determine whether a Thrift TBaseClient is currently busy or available?

In our system, we have one C++ component acting as a Thrift Server, and one .netCore/C# component as a client.
So far, I was managing a single connection, so using a singleton to create my ThriftPushClientWrapper which implements TBaseClient. (via the generated object from the thrift interface)
.AddSingleton<IThriftPushClientWrapper>(sp =>
{
var localIpAddress = IPAddress.Parse(serverIp);
var transport = new TSocketTransport(localIpAddress, dataPort);
var protocol = new TBinaryProtocol(transport);
return new ThriftPushClientWrapper(protocol);
});
(so far using 0.13 version of the Thrift library, need to update to 0.14.1 soon, but wonder if the server part must be updated too/first).
This is working great.
Now, I want multiple clients that can connect to the server simultaneously, all on the same ip:port
So I am starting a ClientFactory, but wonder how to deal with the creation of the client.
To be more precise, the server part is configured for 5 threads, so I need 5 clients.
One simple approach would be to create a new client each time, but probably inefficient.
A better approach is to have a collection of 5 clients, and using the next available free one.
So I started with the following factory, where I should get the index from outside.
private readonly ConcurrentDictionary<int, IThriftPushClientWrapper> _clientDict;
public IThriftPushClientWrapper GetNextAvailablePushClient(int index)
{
IThriftPushClientWrapper client;
if (_clientDict.ContainsKey(index))
{
if (_clientDict.TryGetValue(index, out client) && client != null)
return client;
else // error handling
}
// add new client for the expecting index
client = CreateNewPushClient();
_clientDict.TryAdd(index, client);
return client;
}
private IThriftPushClientWrapper CreateNewPushClient()
{
var localIpAddress = IPAddress.Parse(serverIp);
var transport = new TSocketTransport(localIpAddress, dataPort);
var protocol = new TBinaryProtocol(transport);
return new ThriftPushClientWrapper(protocol);
}
My next issue it to determine how to set the index from outside.
I started with a SemaphoreSlim(5,5) using the semaphore.CurrentCount as index, but probably not the best idea. Also tried with a rolling index from 0 to 5. But apparently, a CancellationToken is used to cancel further procceesing. Not sure the root cause yet.
Is it possible to determine whether a TBaseClient is currently busy or available?
What is the recommended strategy to deal with a pool of clients?
The easiest solution to solve this is to do it right. If you are going to use some resource from a pool of resources, either get it off the pool, or mark it used in some suitable way for that time.
It's notable that the question has nothing to do with Thrift in particular. You are trying to solve a weak resource management approach by trying to leverage other peoples code that was never intended to work in such a context.
Regarding how to implement object pooling, this other question can provide further advice. Also keep in mind that especially on Windows platforms not all system resources can be shared freely across threads.

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.

Webmatrix.Data.Database Connection String Cleared After Form Submit

I'm developing an ASP.NET (Razor v2) Web Site, and using the WebMatrix.Data library to connect to a remote DB. I have the Database wrapped in a singleton, because it seemed like a better idea than constantly opening and closing DB connections, implemented like so:
public class DB
{
private static DB sInstance = null;
private Database mDatabase = null;
public static DB Instance
{
get
{
if (sInstance == null)
{
sInstance = new DB();
}
return sInstance;
}
}
private DB()
{
mDatabase = Database.Open("<Connection String name from web.config>");
return;
}
<Query Functions Go Here>
}
("Database" here refers to the WebMatrix.Data.Database class)
The first time I load my page with the form on it and submit, a watch of mDatabase's Database.Connection property shows the following: (Sorry, not enough rep to post images yet.)
http://i.stack.imgur.com/jJ1RK.png
The form submits, the page reloads, the submitted data shows up, everything is a-ok. Then I enter new data and submit the form again, and here's the watch:
http://i.stack.imgur.com/Zorv0.png
The Connection has been closed and its Connection String blanked, despite not calling Database.Close() anywhere in my code. I have absolutely no idea what is causing this, has anyone seen it before?
I'm currently working around the problem by calling Database.Open() before and Database.Close() immediately after every query, which seems inefficient.
The Web Pages framework will ensure that connections opened via the Database helper class are closed and disposed when the current page has finished executing. This is by design. It is also why you rarely see connections explicitly closed in any Web Pages tutorial where the Database helper is used.
It is very rarely a good idea to have permanently opened connections in ASP.NET applications. It can cause memory leaks. When Close is called, the connection is not actually terminated by default. It is returned to a pool of connections that are kept alive by ADO.NET connection pooling. That way, the effort required to instantiate new connections is minimised but managed properly. So all you need to do is call Database.Open in each page. It's the recommended approach.

How to invalidate ASP.NET cache if data changes in PostgreSql database

ASP.NET/MONO MVC2 application standard ASP.NET Web cache is used to speed up database access:
string GetName() {
// todo: dedect if data has changed and invalidate cache
var name = (string)HttpContext.Current.Cache["Name"];
if (name!=null)
return name;
name = db.Query("SELECT name from mydata");
HttpContext.Current.Cache.Insert("Name", name);
return name;
}
mydata can changed by other application.
In this case this method returns wrong data.
How to detect if data is changed and return fresh data from PostgreSql database in this case ?
It is OK to clear whole Web cache if mydata has changed.
The best way to do this is likely with LISTEN and NOTIFY.
Have your app maintain a background worker with a persistent connection to the DB. In that connection, issue a LISTEN name_changed, then wait for notifications. If npgsql supports it it might offer a callback; otherwise you'll have to poll.
Add a trigger to the name table that issues a NOTIFY name_changed.
When your background worker gets the notification it can flush the cache.
You can even use the NOTIFY payload to invalidate only changed entries selectively.

Is profile data for current user retrieved just once

a) When current user accesses Profile object for the first time, does Asp.Net
retrieve a complete profile for that user or are profile properties retrieved one at the time as they are called?
b) In any case, is profile data for current user retrieved from DB each time it is called or is it retrieved just once and then saved for the duration of current request?
thanx
You don't specify if this is a Website Project or a Web Application Project; when it comes to profiles there is a big difference as they are not implemented out of the box for the Web Application Project template:
http://codersbarn.com/post/2008/07/10/ASPNET-PayPal-Subscriptions-IPN.aspx
http://leedumond.com/blog/asp-net-profiles-in-web-application-projects/
Have you actually implemented it yet or are you just in the planning stage? If the latter, then the above links should provide some valuable info. As regards the caching issue, I would go with Dave's advice.
If you want to save a database call, you can use a utility method to cache the profile or you can implement your own custom MembershipProvider which handles the caching.
The utility method is probably the simplest solution in this case unless you have other functionality you want to implement which would be served by implementing a custom MembershipProvider.
You can refer to this link for more details:
How can I access UserId in ASP.NET Membership without using Membership.GetUser()?
Here's an example of a utility method to do caching. You can pass a slidingMinutesToExpire to make it expire from the cache after some duration of time to avoid consuming excess server memory if you have many users.
public static void AddToCache(string key, Object value, int slidingMinutesToExpire)
{
if (slidingMinutesToExpire == 0)
{
HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.NotRemovable, null);
}
else
{
HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(slidingMinutesToExpire), System.Web.Caching.CacheItemPriority.NotRemovable, null);
}
}

Resources