I have following code for my Controller Class. I refresh my View from the controller. Every time Refresh takes place, my whole class constructor is called, I wanted to refresh only my Show function and its attached View. How to avoid this constructor getting called every time.
public class DriverController : Controller
{
OdbcConnection DBConnection; //= new OdbcConnection("DSN=pitbuccx");
OdbcConnection DBConnection2; // = new OdbcConnection("DSN=pitbuccx2");
Query q;
string myQuery;
OdbcCommand cmd;
OdbcCommand cmd2;
OdbcDataReader DbReader;
OdbcDataReader DbReader2;
string LoggedInAgents;
string OnCalls;
string AgentsInReadyState;
string AgentsInNotReadyState;
string AgentsInWrapup;
string ReservedAgents;
string CallsOffered;
string CallsAnswered;
string CallsAbandoned;
string CallsInQueue;
string LongestCallInQueue;
string AbandRate;
string ServiceLevelPct;
string ASA;
string AHT;
string LongestTalkDuration;
public DriverController()
{
OdbcConnection DBConnection = new OdbcConnection("DSN=pitbuccx01");
DBConnection.Open();
OdbcConnection DBConnection2 = new OdbcConnection("DSN=pitbuccx02");
DBConnection2.Open();
q = new Query();
myQuery = q.getQuery();
cmd = DBConnection.CreateCommand();
cmd2 = DBConnection2.CreateCommand();
cmd.CommandText = myQuery;
cmd2.CommandText = myQuery;
Console.WriteLine("This is Constructor");
}
public ActionResult Show()
{
DbReader = cmd.ExecuteReader();
DbReader2 = cmd2.ExecuteReader();
DbReader.Read();
DbReader2.Read();
string testData1;
string testData2;
//Checking Connection Data Validity.
testData1 = DbReader["A"].ToString();
testData2 = DbReader2["B"].ToString();
Response.AddHeader("Refresh", "5");
return View();
}
}
~DriverController()
{
DbReader.Close();
cmd.Dispose();
DBConnection.Close();
DbReader2.Close();
cmd2.Dispose();
DBConnection2.Close();
}
You should not be doing this in your controller. By definition a controller is the director of web requests. At the minimum you need a domain type to create and release external resources like DB connections, and do queries against the data source. I can't even see where connections are being closed/disposed.
How to avoid controller instantiation for every request?
You can do that by implementing and registering your own controller factory, which instantiates a given controller only once and then stores it somewhere in the AppDomain so it stays alive for longer than the current request, for example in some static variable.
This question however reeks like an XY problem. You seem to be concerned with the relative cost of opening a database connection for every request.
Well good news, everybody! You're not the first to think about this, and you should not worry, because that has already been fixed long ago by the framework builders: .NET uses connection pooling.
In short, this means that you should not worry about opening database connections, because an earlier opened connection will be saved in the pool and returned to your application when it requests it.
Related
While working on legacy code, I ran into Specific scenario and made a dummy example to show the issue to ask for any suggestions. I get following error:
`
Program.cs(37,1) : warning : CA2100 : Microsoft.Security : The query string passed to 'OleDbCommand.CommandText.set(string)' in 'Program.Read(OleDbConnection, string)' could contain the following variables 'sqlQuery'. If any of these variables could come from user input, consider using a stored procedure or a parameterized SQL query instead of building the query with string concatenations.
My Code is:
class Program
{
static void Main ()
{
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Newfolder\database1.mdb";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
try
{
connection.Open();
string strsql = "SELECT * FROM Table1";
Read(connection,strsql);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static void Read (OleDbConnection connection,string sqlQuery)
{
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = sqlQuery;
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader["PName"]);
}
}
}
Now I cannot go with the solution to suppress warning. There are several complicated situations from which i get these warnings, this is just a dummy simple example to show workflow.
So although the query being executed is safe, but since it comes outside of the function, it asks me to changed it to parametrized query.
As in Read() function, although my input paramter sqlQuery is not from user, but it will come from outside as an input parameter and I cannot move sqlQuery code within the Read() function, it will always come from outside based on which certain decisions are made.
So what can I do to make this redundant warning disapper?
My dummy Access databse snapshot is this:
I have tried going through Microsoft official documentation on it, but i was not able to come up with solution
First off, prior to asking this question I have been researching connection pooling for the better part of my morning. What I've found is that is turned on by default, handled by the application/system, and C#'s System.Data.X namespaces (where X is something like OLEDBConnection / SqlConnection ) handles it automatically.
But as I'm still new to the whole database access and pooling, I am looking for clarification since I wrote a class to handle connections at a higher level.
public abstract class AbstractDatabase<T> where T: where T : System.Data.Common.DbConnection
{
// Take this class's connection string and return a new connection object
public abstract T GetConnection();
public abstract SqlKata.Compilers.Compiler { get; }
// Compile the query and return a DataTable
// This is actually pointing to a static method that uses the IDBConnection interface and logs any errors, but I copied the relavant code here
public virtual DataTable GetDataTable(SqlKata.Query query)
{
using (var Conn = GetConnection())
{
if (Conn.State == ConnectionState.Closed) Conn.Open();
using (var Cmd = Conn.CreateCommand())
{
Cmd.CommandType = CommandType.Text;
Cmd.Connection = Conn;
Cmd.CommandText = Compiler.Compile(Query).ToString(); // the query is fully formed string here
Cmd.Parameters.AddDummyParameter(); // I noticed that without any parameters, this didn't work, so this method adds a dummy, even if the string doesn't have any '?' characters
using (var DR = Cmd.ExecuteReader())
{
DataTable DT = new DataTable();
DT.Load(DR);
return DT;
}
}
}
}
}
public class SomeDatabase : AbstractDatabase<OleDbConnection>
{
// class implementation
}
here is my question:
If I were to somewhere else in my program do something like this:
DataTable Tbl1 = SomeDatabase.GetDataTable(Query1);
DataTable Tbl2 = SomeDatabase.GetDataTable(Query2);
....
DataTable Tbl10 = SomeDatabase.GetDataTable(Query10);
My understanding is that the method's Using ( var Conn = GetConnection()) statement will automatically issue a Conn.Close() and dispose of the Conn as the method exits. But connection pooling is automatically enabled, so it will actually reuse that connection almost immediately instead of closing it, correct?
With that level of abstraction, does it make sense to write it like this?
using ( var conn = SomeDatabase.GetConnection())
{
DataTable Tbl1 = SomeDatabase.GetDataTable(Query1);
....
DataTable Tbl10 = SomeDatabase.GetDataTable(Query10);
}
Would this make any difference?
Should the method be written to accept the connection that already open ?
Should the class be written to use the same connection object itself, rather than calling GetConnection() every time ? ( for example, a get-only property that initializes the backing field on first request to it, then all subsequent requests actually receive the backing field's object)
Is there a way to call a Snowflake Stored Procedure asynchronously from .Net? I am running a .Net Core API App using Snowflake’s DotNet driver. Basically I need to be able to use conn.OpenAsync and cmd.ExecuteNonQueryAsync like you normally would with a SQL Server, but that seems to be impossible.
executeResults.SessionId =RunNonQueryAsync(connectionString, command).Result;
static async Task<String> RunNonQueryAsync(string execConnection, string execCommand)
{
String sessionId = null;
using (IDbConnection conn = new SnowflakeDbConnection())
{
conn.ConnectionString = execConnection;
conn.Open();
// Get Session Information
IDbCommand cmd2 = conn.CreateCommand();
cmd2.CommandText = "SELECT CURRENT_SESSION() as SESSION_ID";
IDataReader rdr2 = cmd2.ExecuteReader();
while (rdr2.Read())
{
sessionId = rdr2.GetValue(0).ToString();
}
Task taskA = new Task(() =>
{
using (IDbConnection cn = new SnowflakeDbConnection())
{
cn.ConnectionString = execConnection;
cn.Open();
IDbCommand cm = conn.CreateCommand();
cm.CommandText = "call StoredProcedureThatTakes5MinutesToRun";
cn.Close();
}
});
taskA.Start();
}
return sessionId;
}
My browser sends an HTTP GET which the DotNet API receives along with the properties [SQL Type: "NonQuery" AND StatementText:"Call StoredProcX"].
That sounds like a absolute security nightmare. SQL Injections are bad enough, but that is basically putting a Central Venous Catheter into your Database.
At best, I would allow some simple Enumeration, integer or string value to be send with the request. One that is then passed through a switch/case statement. Maybe fed into a Dictionary<String, Action>, if that works better. The case or the action will then do the work of sending off the requests.
From there it is really just doing two things within then same connection:
using (IDbConnection cn = new SnowflakeDbConnection())
{
cn.Open();
//Build command 1
//Execute command 1
//Do stuff with results of command 1
//Build command 2
//Execute command 2
//Do stuff with results of command 2
//Can propably be omited, as Dispose usually includes close. But we are talking about some 3rd party code, that might not be tested that well
cn.Close();
}
I want to create a class that has SQL connection and functions (like insert, select, delete queries) and I want to call it to my forms (buttons and etc.)
I don't know if it's possible or not or maybe there are some ways on doing this so...
I've done some research and come up with this code on class SQL connection and I'm not sure if it's correct.
Thank you very much in advance. I'm a beginner and want to learn more on c#.
Any type of response is appreciated. Thank you
Sorry for my bad English
using System.Data.SqlClient;
class SqlConnClass
{
public static SqlConnection GetConnection()
{
string str = "Data Source=localhost;Initial Catalog=kwem;Integrated Security=True;";
SqlConnection conn = new SqlConnection(str);
conn.Open();
return conn;
}
You were close! You may want to take the `conn.Open()' out of your method as you can open it for your query. (Remember to close it or put it in a using statement!)
public static void UpdateDB(string valToUpdate)
{
SQLConnection conn = GetConnection();
using (conn)
{
SQLCommand updateCommand = new SQLCommand(GetConnection(), "Update Table
Set Val = #newValue");
updateCommand.Parameters.AddWithValue("#newValue", valToUpdate);
conn.Open();
updateCommand.ExecuteNonQuery();
}
}
You would then do the same for any other kind of DB functions.
It's true but; if your string str do not work. Please try this:
string str = "Data Source=local host ;Initial Catalog=kwem;Integrated Security=True"
also you need to define sql table and then select your database.
You are on the right path.
What you are referring to is called a data access layer, or DAL for short.
It's a part of the n-tier architecture model (in the simple version there are 3 tiers - presentation, business logic and data access layer).
The basic concept is that you separate the presentation, logic and data into 3 different parts of the application.
As for the data access layer, usually you'll have a static or singleton class responsible to connect the business layer to the data. This class will contain methods for CRUD operations - Create, Read, Update and Delete data. You will need to create methods for each operation and for each data entity.
One approach I see all the time is this:
public static class DAL
{
private static string _ConnectionString = null;
static DAL() // A static constructor to initialize the connection string
{
_ConnectionString = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
}
public static DataSet GetCategories()
{
var ds = new DataSet();
var sql = "SELECT * FROM Categories";
using (var con = new SqlConnection(_ConnectionString))
{
using (var cmd = new SqlCommand(sql, con))
{
using (var adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(ds);
}
}
}
return ds;
}
public static int DeleteCategory(int categoryId)
{
int rowsEffected = 0;
var sql = "DELETE FROM Categories WHERE Id = #Id";
using (var con = new SqlConnection(_ConnectionString))
{
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.Add("#Id", SqlDbType.Int).Value = categoryId;
con.Open();
cmd.ExecuteNonQuery();
}
}
return rowsEffected;
}
}
and so on. As you can see, there is a lot of code that repeats itself.
This means longer code, herder maintenance, and if for some reason you will want to support other types of databases (like migrating to MySql, Oracle or whatever) You will have to work very hard to change all the vendor specific classes in your DAL (SqlConnection, SqlCommand etc`).
These problems are exactly the reason I wrote ADONETHelper. I've been using it for a few years (mostly in earlier, different forms) and I feel now it's matured enough to go public. It's currently under MIT licence, meaning it's completely free and you can download your copy and change it as you see fit.
Should you choose to use it, your DAL class should probably look like this:
public static class DAL
{
private static IDBHelper _DB;
static DAL() // A static constructor to initialize _DB
{
// initialize connection string from config file
var connectionstring = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
_DB = DBHelperFactory.GetInstance(DataBaseType.SQLServer, connectionstring);
}
public static DataSet GetCategories()
{
var sql = "SELECT * FROM Categories";
return _DB.FillDataSet(sql, CommandType.Text);
}
public static int DeleteCategory(int categoryId)
{
var sql = "DELETE FROM Categories WHERE Id = #Id";
var param = _DB.CreateParameter("#Id", ADONETType.Int, categoryId);
return _DB.ExecuteNonQuery(sql, CommandType.Text, param);
}
}
As you can see, code repetitions are down to the bare minimum, and migrating to a different database is as simple as changing the static constructor to use a different DataBaseType. Of course, if you are using vendor-specific sql you will have to change that too.
I'm setting up a connection factory for a .NET project, and I'd like to ask what is the best way for it.
I have an issue with the previous Log class not being able to write the logs properly because of table LOCKS (or so they say), so I'm tasked with setting up a new data layer that (hopefully) solves this along some other minor issues.
For now, the code:
public sealed class ConnectionFactory
{
//Will be SQL only
private static SqlConnection sqlConnection = null;
private static string connectionString = ConfigurationManager.ConnectionStrings["Development"].ConnectionString;
public static SqlConnection GetConnection()
{
if(sqlConnection == null)
{
sqlConnection = new SqlConnection();
sqlConnection.Open();
}
return sqlConnection;
}
}
I'll be using mostly procedures, but may have one or another weird request and we'll type a query if needed, so I'm think I have to add a SqlCommand somehow:
private static SqlCommand sqlCommand = null;
public static SqlCommand GetCommand()
{
//Check if sqlConnection is not null (omitted)
if(sqlCommand == null)
{
sqlCommand = sqlConnection.CreateCommand();
}
return sqlCommand;
}
However, should this command be static? Or should I create a new one each time a new query is going to be executed?
Thinking in avoiding locks mostly, can it be caused by having multiple commands or only multiple connections? How do I avoid and deal with this properly?
I believe a "nolock" would work in this case...
FROM [table] with (nolock)
whenever you do a direct query.