How to write unit case for remote database connection in asp web application - asp.net

I am new to unit testing for web applications
I have a function which creates a connection to a remote mysql database and perform some operations on it .
I want to have a test case which tests the connection is closed or not after the operations on database.
for example
fun1()
{
ODBCConnection con = new ODBCConnection(connString);
con.open();
}
in the above function, the connection is not closed?
how do i check this? can any one help?

In .Net, it's generally best to open your connections immediately before you use them. So rather than building (and testing) a function that connects to the database, you build and test a function that returns the correct connectionstring. You also have a reference database for your testing environment, and so you build your data access methods and create their own connection and test them against your reference database, that the right results come back.
Okay, based on your comment I can help you. Since you will be opening and closing the connection in the same function (as you should), you can do this:
public void fun1()
{
using (ODBCConnection con = new ODBCConnection(connString))
{
con.open();
//use the connection here
}
//connection is closed here because of the using block, even if an exception is thrown
}
There is no need to check if the connection closes in the code above. It will be closed in a timely manner by the using block, and that's guaranteed as much as anything can be in software. Just make sure you use that pattern everywhere you use connections.
In unit testing, the "units" to be tested are methods/functions. You test that the function performs as you expect it to, and nothing more. If you want to test specifically if a connection is closed, than the way to do it is to write a function to close the connection, and test that.

Related

multiple SqlConnections for one feature: bad idea?

I got an asp.net gridview connected to my sql database. When Inserting a new record or updating a record im doing some serverside checks and then either update/insert a record or do nothing. right now i got 2 methods CheckArtistExists and CheckSongExists which are both using a SqlConnection Object e.g.
public bool CheckSongExists(string _title, int _artistId)
{
int cnt = -1;
using (SqlConnection con = new SqlConnection(CS))
{
//check if song already is exists in DB
SqlCommand cmd = new SqlCommand("Select Count(ID) from tblSong WHERE Title = #newTitle AND ArtistId = #newArtistId;", con);
cmd.Parameters.AddWithValue(#"newTitle", _title);
cmd.Parameters.AddWithValue(#"newArtistId", _artistId);
con.Open();
cnt = (int)cmd.ExecuteScalar();
// if cnt ==1 song exists in DB, of cnt == 0 song doesnt exist
if(cnt == 1)
{ return true; }
else
{ return false; }
}
}
So for the Update function in the gridview i need to establish 3 SqlConnections (at max) one to check for the artist(if artist doesnt exist i have to insert a record to tblArtist first)
then a check if the song exists(only if artist exists) and finally if song doesnt exist I have to insert a new record.
I know database connections are valuable resources thats why i put them in a using block. So im not quite sure if its good style to use 3 SqlConnection objects to update/insert. Can you please tell me if my code is ok or if i should rather use another approach for this problem.
thank you
ADO.NET internally manages the underlying Connections to the DBMS in the ADO-NET Connection-Pool:
In practice, most applications use only one or a few different
configurations for connections. This means that during application
execution, many identical connections will be repeatedly opened and
closed. To minimize the cost of opening connections, ADO.NET uses an
optimization technique called connection pooling.
Connection pooling reduces the number of times that new connections
must be opened. The pooler maintains ownership of the physical
connection. It manages connections by keeping alive a set of active
connections for each given connection configuration. Whenever a user
calls Open on a connection, the pooler looks for an available
connection in the pool. If a pooled connection is available, it
returns it to the caller instead of opening a new connection. When the
application calls Close on the connection, the pooler returns it to
the pooled set of active connections instead of closing it. Once the
connection is returned to the pool, it is ready to be reused on the
next Open call.
So obviously there's no reason to avoid creating,opening or closing connections since actually they aren't created, opened and closed at all. This is "only" a flag for the connection pool to know when a connection can be reused or not. But it's a very important flag, because if a connection is "in use"(the connection pool assumes), a new physical connection must be openend to the DBMS what is very expensive.
So you're gaining no performance improvement if you "reuse" connections but the opposite.
Create, open(in case of Connections), use, close and dispose them where you need them(f.e. in a method)
use the using-statement to dispose and close(in case of Connections) implicitely
So yes, it's absolutely fine to use one connection per method since you are not using a physical connection at all if connection-pooling is enabled (default).
Another question is if you could improve your approach. You could create a stored-procedure which checks existence and updates or inserts accordingly.
Solutions for INSERT OR UPDATE on SQL Server

Constructing the Connection String for the DataContext Class

I see a couple of DataContext connection string questions. I'm going to try to differentiate this one a bit:
How does one construct a generic connection string to a database, localhost | User-PC\User | Some database... (it is hosted/managed by Microsoft SQL 2008)
I notice that it is IDisposable. So if I have multiple users hitting my site, my code can only access the database one instance at a time, and has to wait until each instance is disposed, in order for the data to be consistent for each user?
Is it possible, by any chance, to somehow enable LINQ in F#-Interactive, and connect to the database from there? I cannot figure out how to enable/load the System.Data dll into fsi. Maybe that is unique to my installation, or it is a common thread? (ie, my installation also does not recognize windows.base.dll--I have to manually get it from programs\reference assemblies).
Anyhow, I've pretty much conclusively discovered that
let x = new System.Data.Linq.DataContext("localhost")
...does not work.
1) How does one construct a generic connection string to a database?
There is no generic way to construct a connection string. The best thing to do is to keep the connection string in some configuration file where you can change it depending on your configuration (the name of SQL Server machine, authentication options, whether it is a file-based database or normal). There is a web site with examples for most of the options.
2) I notice that it is IDisposable. So if I have multiple users hitting my site, my code can only access the database one instance at a time [...]?
No, this is not how DataContext works. The DataContext does not keep a live connection to the server that would block anybody else from using the SQL server. It keeps some state (i.e. cached entities that were already obtained) and it uses optimistic concurrency to make sure that the state is consistent (you can use transactions to prevent other connections, if that's what you want).
3) Is it possible, by any chance, to somehow enable LINQ in F#-Interactive [...]?
That shouldn't be a problem. You can reference assemblies using #r "foo.dll" in F# interactive. The typical approach for F# 2.0 is to generate the data context using C# tools and then just reference it (for F# 3.0, things are easier because you can just use type provider).
If you generate LINQ to SQL data context for Northwind in C#, the F# Interactive use would look like this:
#r #"<whatever_path>\Northwind.dll"
#r "System.Data.Linq.dll"
open Northwind
open Microsoft.FSharp.Linq
let connStr = #"Data Source=.\SQLEXPRESS;AttachDbFilename=<path>\NORTHWND.MDF;" +
#"Integrated Security=True;User Instance=True"
let operation () =
// Using 'use' to make sure it gets disposed at the end
use db = new NorthwindDataContext(connStr)
// do something with the database
There actually is a somewhat generic way to construct a connection string:
open System.Data.Common
open System.Data.SqlClient
let providerName = "System.Data.SqlClient"
let factory = DbProviderFactories.GetFactory(providerName)
let cnBuilder = factory.CreateConnectionStringBuilder() :?> SqlConnectionStringBuilder
cnBuilder.DataSource <- "localhost"
cnBuilder.InitialCatalog <- "MyDatabase"
cnBuilder.IntegratedSecurity <- true
let connStr = cnBuilder.ConnectionString
My approach was to have 1 connection string and then use that for all of my DataContext connections. So this code builds the EntityConnectionString based on MyConnString:
protected override MyEntities CreateObjectContext()
{
string ConnString =ConfigurationManager.ConnectionStrings["MyConnString"];
string seConn = ConfigurationManager.ConnectionStrings["MyEntities"].ToString();
EntityConnectionStringBuilder ecsb = new EntityConnectionStringBuilder(seConn);
ecsb.ProviderConnectionString = ConnString;
EntityConnection ec = new EntityConnection(ecsb.ToString());
ScheduleEntities ctx = new ScheduleEntities(ec);
return ctx;
}

Closing database connection in asp.net

Can we close all known/unknown connections to database with the code?
I'm using Access database and my application gives the following error:
"Could not use ''; file already in use. "
I don't know which connection is opened and no closed, so is there a way to close all application's opened connections?
When working with disposable objects you should use using so they will get disposed, and in this case even closed, when leaving the using block. Your code should look something like:
using (var connection = new OleDbConnection(connectionString))
{
connection.Open();
// Do work here; connection closed on following line.
}
Read about OleDbConnection.
UPDATE: I missed that you were accessing an access database, so updated the code to use OleDbConnection instead.

asp.net webservice OnUnload?

I'm creating a web service which has a number of methods, all of which make use of a SqlConnection. It seems logical that I would declare a class level connection and initialise it in the web service constructor.
Problem is I cannot find a definitive way to release the connection when the web service call completes, so I have a connection leak. I've tried overriding the Dipose() method but it doesn't get called in a reasonable timeframe (actually not at all in my testing). For good measure I also tried attaching a handler to the Disposed() event but as expected same problem.
Is there nothing similar to Page.OnUnload for web service classes? It seems hard to believe I would have to establish a separate connection in every individual method.
Any suggestions?
It seems logical that I would declare a class level connection and initialise it in the web service constructor.
No, this doesn't seem logical at all. ADO.NET uses a connection pooling so that you don't need to do this. This connection pool is per connection string per application domain.
So you could simply draw a new connection from the pool in each web method and return it to the pool at the end (the using statements will take care of this):
[WebMethod]
public void Foo()
{
// Here you are NOT creating a new connection to the database
// you are just drawing one from the connection pool
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
// Here you are NOT opening a new connection to the database
conn.Open();
cmd.CommandText = "SELECT id FROM foo";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do something with the results
}
}
} // Here you are NOT closing the connection, you are just returning it to the pool
}
So here's an advice: don't try to manage connections manually by using some class fields, static fields, ... Leave this management to ADO.NET as it does it better.
Remark: The code I've shown usually resides in a data access layer which is called by the web method.

AS400 Data Connection in ASP.NET

I have an application that will reside within a business2business network that will communicate with our AS400 in our internal network environment. The firewall has been configured to allow the data request through to our AS400, but we are seeing a huge lag time in connection speed and response time. For example what takes less than a half second in our local development environments is taking upwards of 120 seconds in our B2B environment.
This is the function that we are utilizing to get our data. We are using the enterprise library application blocks, so the ASI object is the Database...
/// <summary>
/// Generic function to retrieve data table from AS400
/// </summary>
/// <param name="sql">SQL String</param>
/// <returns></returns>
private DataTable GetASIDataTable(string sql)
{
DataTable tbl = null;
HttpContext.Current.Trace.Warn("GetASIDataTable(" + sql + ") BEGIN");
using (var cmd = ASI.GetSqlStringCommand(sql))
{
using (var ds = ASI.ExecuteDataSet(cmd))
{
if (ds.Tables.Count > 0) tbl = ds.Tables[0];
}
}
HttpContext.Current.Trace.Warn("GetASIDataTable() END");
return tbl;
}
I am trying to brainstorm some ideas to consider as to why this is occurring.
Have never used ASP.NET or AS400 in anger, but I have seen this kind of behaviour before and it usually indicated some kind of network problem, typically a reverse DNS lookup that is timing out.
Assuming you have ping enabled through your firewall, check that you can ping in both directions.
Also run traceroute from each machine to try and diagnose where a delay might be.
Hope that helps.
Sorry but I can't tell you what is going on but I just have a couple comments...
First I would output the sql, see if it has a lot of joins and/or is hitting a table (file) with a large amount of records. If you really want to dig in fire up your profiler of choice (I use Ants Profiler) and try to find a profiler for the 400 - see what the server resources are as well as actual query after it goes thru the odbc driver.
I have worked with asp.net and as400 a few times and the way I have been most successful is actually using sql server with a linked server to AS400. I created a view to make it simpler to work with - hiding the oddities of as400 naming. It worked well in my scenario because the application needed to pull information from sql server anyway.
I thought I would mention it in case it helps... best of luck
Check the size of your iSeries system as well. Depending on the size of the query and if the system is undersized for the applications running on it, this may take time. While it shouldn't be thrown out as a posibility, I have seen a similar behavior in the past. But of course more likely is a network issue.
The other idea if you can solve the speed issue or is a sizing problem is to store it in an MS SQL Server then write the records from SQL Server to the iSeries from there.

Resources