Access command object from SqlDataReader - c#

Having a SqlDataReader object, I am trying to get the timeout of its related command. For example I am using this to create my SqlDataReader:
SqlCommand myCommand = new SqlCommand(query, some_connection);
_reader = myCommand.ExecuteReader();
In run-time using visual debugger I can access to this using :
_reader.Command.CommandTimeout // Visual debugger
No how can I do access this "property" in my code (I would like to expose this as a property for a third party lib)?
Context:
I am accessing the reader from a third library, so actually I just have access to the reader. My question is to understand why I can access the command in the debugger and not as a property? What is the mechanism behind the scene, some property extension, reflection?

You will need to use Reflection to get hold of the Command property, as it is set to internal access. This is what the debugger uses to show you the properties.
PropertyInfo prop = _reader.GetType().GetProperty("Command",
BindingFlags.NonPublic | BindingFlags.Instance);
DbCommand cmd = (DbCommand)prop.GetValue(_reader);
int timeout = cmd.CommandTimeout;
P.S. You shouldn't really be unit testing third party components - that is the same as saying "I don't trust the .NET framework to do it's job so I'll check everything it's doing internally". If you want to test it, put the unit tests inside the third party solution.

I suggest to provide a facade (wrapper) for the SqlCommand and SqlConnection. Then pass this object to the third party library.
public class MyOwnReader : IDisposable
{
bool isDisposed = false;
SqlConnection _connection;
SqlCommand _command;
// You can expose the whole command, or specific property of the command
public SqlCommand Command
{
get
{
return _command;
}
}
public MyOwnReader(string connectionString)
{
_connection = new SqlConnection(connectionString);
_connection.Open();
_command = new SqlCommand();
_command.Connection = _connection;
_command.CommandType = CommandType.StoredProcedure; //example initialization
}
public void Dispose()
{
if (!isDisposed)
{
_connection.Dispose();
_command.Dispose();
isDisposed = true;
}
}
public SqlDataReader ExecuteReader()
{
return _command.ExecuteReader();
}
}

Related

C# overloaded constructors issue

I have the following class that I use to minimise code duplication when often calling different sets of data from an Oracle database. Primarily I need help to remove the code duplication in the overloaded constructor, but any other advice would be appreciated too.
public class UniformData
{
private string connection = "My Connection String";
private OracleConnection con;
private OracleCommand com;
private OracleDataReader reader;
public UniformData(string sql)
{
con = new OracleConnection(connection);
con.Open();
com = new OracleCommand(sql, con);
}
public UniformData(string sql, List<SqlParameters> myParams)
{
con = new OracleConnection(connection);
con.Open();
com = new OracleCommand(sql, con);
foreach (SqlParameters Param in myParams)
{
com.Parameters.Add(Param.ParamName, Param.ParamValue);
}
}
public OracleDataReader GetReader()
{
reader = com.ExecuteReader();
return reader;
}
~UniformData()
{
con.Close();
con.Dispose();
com.Dispose();
reader.Close();
reader.Dispose();
}
}
Normally I'd have a "canonical" constructor which all the other constructors chain to. In your case that would involve creating an empty list though:
public UniformData(string sql) : this(sql, new List<SqlParameters>())
{
}
public UniformData(string sql, List<SqlParameters> parameters)
{
con = new OracleConnection(connection);
con.Open();
com = new OracleCommand(sql, con);
foreach (SqlParameters parameter in parameters)
{
com.Parameters.Add(parameter.ParamName, parameter.ParamValue);
}
}
Alternatively, change the type of the parameter to IEnumerable<SqlParameters> at which point you can use Enumerable.Empty:
public UniformData(string sql) : this(sql, Enumerable.Empty<SqlParameters>())
{
}
public UniformData(string sql, IEnumerable<SqlParameters> parameters)
{
// Body as before
}
You can split the work the other way, as Mong Zhu's code does - but I tend to find it cleaner to keep all the work in a single place where possible. That makes it easy to validate that you've initialized all your variables properly in all cases - you only need to check that all constructors chain to the canonical one, and that the canonical one initializes everything.
Additionally I would:
Make your class implement IDisposable
Remove the finalizers
you can call the simpler constructor from the more complex one using this(parameter)
public UniformData(string sql)
{
con = new OracleConnection(connection);
con.Open();
com = new OracleCommand(sql, con);
}
public UniformData(string sql, List<SqlParameters> myParams): this(sql)
{
foreach (SqlParameters Param in myParams)
{
com.Parameters.Add(Param.ParamName, Param.ParamValue);
}
}
The original post is 7 years old, may be you missed it when researching.
The Using Constructors (C# Programming Guide) might yield further helpful information including my answer
Simply have one of the constructors call the other. Either have the overload without the parameters call the overload with the parameters, but passing an empty list, or have the overload with parameters call the overload without parameters to initialize the connection, so that it only needs to add the parameters.

How to unit test database methods in C#?

I've searched everywhere, but nothing I found was applicable to my current situation.
I have a class that helps with DB connections, and I need to unit test some of its methods:
public class DBHelper
{
private SqlConnection conn;
private SqlCommand textCommand;
public DBHelper(IDbConnection connection)
{
conn = (SqlConnection)connection;
textCommand = new SqlCommand();
textCommand.Connection = conn;
}
public SqlConnection Conn
{
get
{
return conn;
}
set
{
if (conn != null)
{
conn.Close();
conn.Dispose();
}
conn = (SqlConnection)value;
textCommand = new SqlCommand();
textCommand.Connection = conn;
textCommand.CommandType = CommandType.Text;
}
}
public object QueryScalar(string query)
{
textCommand.CommandText = query;
string qtype = query.Substring(0, 6).ToLower();
if (qtype == "select")
return textCommand.ExecuteScalar();
return textCommand.ExecuteNonQuery();
}
}
I know I shouldn't access the database from the test. I tried using mock objects but I don't think they can help here, because I cannot change textCommand from the outside of the class. I tried setting up an SQLite database and accessing it through SQL, but to no avail.
My question is: How can I unit test QueryScalar method?
Thank you for any ideas.
Perhaps you can use something like this in your class...
private IScalarQuerier _scalarQueryer;
public DBHelper(IDbConnection connection, IScalarQuerier q)
{
_scalarQuerier = q;
conn = (SqlConnection)connection;
textCommand = new SqlCommand();
textCommand.Connection = conn;
}
... and then place the QueryScalar method in a separate class, where you can do / test whatever you want. Just make that class implement an interface IScalarQuerier, so you can pass it in to DBHelper.
Might not be exactly what you were looking for, but this should let you do what you need with the method you want to test.
Sidenote: When you then pass that class (or IScalarQuerier-implementation, to be precise) into DBHelper, you should simply assume that the querier has been tested outside the scope of DBHelper, and that it therefore can be trusted to work correctly.

writing more optimized code and reusing code in C#

I'm writing a desktop application using C# winforms and MSSQL server 2012. there are several classes exit in this application that need to connect to database and all uisng ADO.Net. this is on of my classes :
class Prices
{
private int id = 0;
public int Id
{
get { return id; }
set { id = value; }
}
private string materialName = string.Empty;
......
......
......
public void updateMaterialPrice()
{
string conString = ConfigurationManager.ConnectionStrings["secaloFormulaCS"].ToString();
using (SqlConnection sqlCon = new SqlConnection(conString))
using (SqlCommand sqlCmd = new SqlCommand("spUpdateMaterialPrice", sqlCon))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("materialName",MaterialName);
sqlCmd.Parameters.AddWithValue("unitPrice", Price);
sqlCmd.Parameters.AddWithValue("carbohydrate", Carbohydrtate);
sqlCmd.Parameters.AddWithValue("protein", Proterin);
sqlCmd.Parameters.AddWithValue("fat", Fat);
sqlCmd.Parameters.AddWithValue("humidity", Humadity);
sqlCmd.Parameters.AddWithValue("minerlas", Minerlas);
sqlCon.Open();
sqlCmd.ExecuteNonQuery();
sqlCon.Close();
sqlCon.Dispose();
}
}
public void addMaterial()
{
string ConString = ConfigurationManager.ConnectionStrings["secaloFormulaCS"].ToString();
using(SqlConnection sqlCon = new SqlConnection(ConString))
using(SqlCommand sqlCmd = new SqlCommand("spAddMaterial",sqlCon))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("materialName", MaterialName);
sqlCmd.Parameters.AddWithValue("unitPrice",Price);
sqlCmd.Parameters.AddWithValue("carbohydrate",Carbohydrtate);
sqlCmd.Parameters.AddWithValue("proterin", Proterin);
sqlCmd.Parameters.AddWithValue("fat",Fat);
sqlCmd.Parameters.AddWithValue("humidity", Humadity);
sqlCmd.Parameters.AddWithValue("minerals",Minerlas);
sqlCon.Open();
sqlCmd.ExecuteNonQuery();
sqlCon.Close();
sqlCon.Dispose();
}
as you can see in addMterial() and updateMaterialPrice() i use the same code to connect to database and call a stored procedure and this is repeated for several times in my other classes. how can i prevent this code repetition ? is it any way to just write the code needed for connection and query the database one time and reuse it several times according to situation needed ?
I use a Factory pattern for my Database connections, this means I never have to open a SqlConnection or pass connection strings around my program.
Here is an example for the method I use to run a query that returns multiple rows.
I would call the method from a "makeObject" method that would turn this datatable into an object.
public static class DB
{
private static readonly string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
/// <summary>
/// Use when returning data from multiple rows
/// </summary>
/// <param name="sql">query</param>
/// <param name="parameters">declared parameters</param>
/// <returns>datatable of db rows</returns>
public static DataTable GetDataTable(string sql, SqlParameter[] parameters)
{
try
{
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = sql;
if (parameters != null)
{
foreach (var parameter in parameters)
{
if (parameter != null)
command.Parameters.Add(parameter);
}
}
using (DbDataAdapter adapter = factory.CreateDataAdapter())
{
adapter.SelectCommand = command;
DataTable dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}
}
catch (Exception)
{
throw;
}
}
}
Well, you could make a helper method to prepare the command for you, or at least fill the parameters, eg.
void PrepareParameters(SqlCommand cmd)
{
cmd.Parameters.AddWithValue("materialName",MaterialName);
cmd.Parameters.AddWithValue("unitPrice", Price);
cmd.Parameters.AddWithValue("carbohydrate", Carbohydrtate);
cmd.Parameters.AddWithValue("protein", Proterin);
cmd.Parameters.AddWithValue("fat", Fat);
cmd.Parameters.AddWithValue("humidity", Humadity);
cmd.Parameters.AddWithValue("minerlas", Minerlas);
}
Ideally, unless you want to use a ready ORM like Entity Framework (usually a good idea), you'd create a few abstract classes to handle these kinds of things, so that you'll save on code reuse.
For example, the PrepareParameters method could be abstract, and there could be an abstract property that returns the name of the SP to update, create or delete (or better yet, you could follow a naming scheme so that you'd only need one name). Then you could write 99% of the logic in the abstract base classes, and only prepare the parameters in the actual derived classes, thus cutting code repetition a lot.
Some options are as follows:
Write a SqlHelper class which does the repetitive grunt work of executing a stored procedure. (especially ExecuteNonQuery ones, so that you don't need to worry about return types.)
e.g.
public void ExecuteQuery(string sprocName, SqlParamater[] parameters)
{
// initialize connection
// construct command with sprocName and parameters
// ExecuteNonQuery
}
Use Linq2Sql
This is an excellent quick ORM tool which simplies data access to a great deal.
Use Entity Framework
This is an increasingly used ORM tool.
All of the above approaches have their pros/cons. You need to weight them & select the right method.

Which pattern is better for SqlConnection object?

Which pattern is better for SqlConnection object? Which is better in performance?
Do you offer any other pattern?
class DataAccess1 : IDisposable
{
private SqlConnection connection;
public DataAccess1(string connectionString)
{
connection = new SqlConnection(connectionString);
}
public void Execute(string query)
{
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
// ...
command.Connection.Open();
command.ExecuteNonQuery();
command.Connection.Close();
}
}
public void Dispose()
{
connection.Dispose();
}
}
VS
class DataAccess2 : IDisposable
{
private string connectionString;
public DataAccess2(string connectionString)
{
this.connectionString = connectionString;
}
public void Execute(string query)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = query;
command.CommandType = CommandType.Text;
// ...
command.Connection.Open();
command.ExecuteNonQuery();
command.Connection.Close();
}
}
public void Dispose()
{
}
}
There's no real way to answer this question. The short, canonical answer is that the connection should stay alive for the lifetime of your unit of work. Because we have no way of knowing how DataAccess is used (does it exist for the lifetime of your application, or do you instantiate it and dispose it whenever you do something?), it's impossible to give a concrete answer.
That being said, I would recommend the first pattern, but instantiate and dispose of your DataAccess object as needed; don't keep it around longer than necessary.
Suggest going with DataAccess2. It's a personal preference though. Some might even suggest your class be static. It'd be difficult to say that one is more performant than the other. You're on the path of IDisposable, which is great.
I'd be happy to read and maintain both styles shown above in your question.
Consider having your DAL be able to read the connection string from a .config as well, rather than exclusively allowing the value to be passed in the constructor.
public DataAccess2(string connStr)
{
this.connectionString = connStr;
}
public DataAccess2()
{
this.connectionString =
ConfigurationManager.ConnectionStrings["foo"].ConnectionString;
}
Consider wrapping your SqlCommand in a using as well.
using (var conn = new SqlConnection(connectionString))
{
using(var cmd = conn.CreateCommand())
{
}
}
I think it depends on how your DataAccess object is intended to be used, if it's used within a 'using' clause then the connection is guaranteed to be disposed of after it's done.
But in general I prefer the second pattern as the sql connection is created and disposed of within the Execute method so it's less likely to be left open when you forget to dispose of your DataAccess object.
Considering that sql connection can be a scarse resource I think every attempt should be made to ensure that they're not wasted.
The first will result in errors if you make concurrent calls.
The second will ensure you use a clean connection for each command resulting in more connections being made.
I agree with the statements above that it depends on the scenario for use, to get over the problem related to the first I have a wrapper that needs to use such a pattern so I set a field value boolean to show that a command is being executed on the connection already then "queue" the next command for execution.
There will of course be situations where you may prefer to use multiple connections ...

Using block around a static/singleton resource reference

This is interesting (to me anyway), and I'd like to see if anyone has a good answer and explanation for this behavior.
Say you have a singleton database object (or static database object), and you have it stored in a class Foo.
public class Foo
{
public static SqlConnection DBConn = new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString);
}
Then, lets say that you are cognizant of the usefulness of calling and disposing your connection (pretend for this example that its a one-time use for purposes of illustration). So you decide to use a 'using' block to take care of the Dispose() call.
using (SqlConnection conn = Foo.DBConn)
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SP_YOUR_PROC";
cmd.ExecuteNonQuery();
}
conn.Close();
}
This fails, throwing an exception on the call to open the connection, stating that the "ConnectionString property is not initialized". It's not an issue with pulling the connection string from the app.config/web.config. When you investigate in a debug session you see that Foo.DBConn is not null, but contains empty properties.
Why is this?
A little out of topic and not really answering your question but why using a singleton for SqlConnection when ADO.NET already uses a connection pool? Your code could have very well looked like this:
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SP_YOUR_PROC";
cmd.ExecuteNonQuery();
}
And one less thing to worry about in your program: connection lifecycle
Perhaps you do not have the corresponding connectionStrings node in you web/app.config?
<connectionStrings>
<add name="BAR"
connectionString="Data Source=localhost\sqlexpress;Initial Catalog=mydatabase;User Id=myuser;Password=mypassword;" />
The static field is evaluated sometime before it is used (not deterministically). See beforefieldinit for more detail. So the system may not be ready for creating an SQL-connection when it is called or maybe even properly create the static field after you use it.
Additionally, how would you handle a second SQL-command after you closed the first one? I don't know exactly how SqlConnection works, but after closing (note that this cals Dispose) and disposing the connection, your static Foo.DBConn should be gone, i.e. it won't be reevaluated.
If you want to keep your basic infrastructure, I would replace the static field with a static property which returns a new SqlConnection on get:
public static SqlConnection DBConn
{
get
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString);
}
}

Categories