private void btnSave_Click(object sender, EventArgs e)
{
if(txtFirstName.Text.Trim() != "" && txtLastName.Text.Trim() != "" && txtContact.Text.Trim() != "")
{
Regex reg = new Regex(#"^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$"); //only accepting proper email
Match match = reg.Match(txtEmail.Text.Trim());
if (match.Success)
{ using (SqlConnection sqlCon = new SqlConnection(connectionString)) // connecting info to database
{
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand("ContactAddorEdit", sqlCon);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#PhoneBookID", PhoneBookID); //connecting each value to database
sqlCmd.Parameters.AddWithValue("#FirstName", txtFirstName.Text.Trim());
sqlCmd.Parameters.AddWithValue("#LastName", txtLastName.Text.Trim());
sqlCmd.Parameters.AddWithValue("#Contact", txtContact.Text.Trim());
sqlCmd.Parameters.AddWithValue("#Email", txtEmail.Text.Trim());
sqlCmd.Parameters.AddWithValue("#Address", txtAddress.Text.Trim());
sqlCmd.ExecuteNonQuery(); // executeing the query in database
MessageBox.Show("Submitted successfully"); // showing message when success
Clear(); // clearing the form
GridFill();// refreshing the table
}
}
else
{
MessageBox.Show(" Please enter a valid Email"); // Showing MEssage when email is not valid
}
}
else
{
MessageBox.Show("Please fill Mandatory fields"); // if no input this message will show
}
These codes are under a "save" button in a form and i wanted to call them in the unit test class in order to test them out. Any idea what should i do? Thank you
First, congratulations on trying to figure out how to write unit tests. Isolating code into testable units is a habit that leads to all sorts of great patterns.
There's a lot of ideas about how we might set something like this up, but all I'm going to put here are some steps in the direction of isolating code for testing without changing the code itself very much.
I wouldn't stop with this - in fact, in a short time after reading and learning more you'll probably pick up some even better techniques. I feel the need to point that out because what I'm describing here is a step, not a final destination.
First, you could move your SQL code to a class like this:
public class SqlCommands
{
private readonly string _connectionString;
public SqlCommands(string connectionString)
{
_connectionString = connectionString;
}
public void InsertUpdateContact(InsertUpdateContactParameters parameters)
{
using (SqlConnection sqlCon = new SqlConnection(_connectionString))
{
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand("ContactAddorEdit", sqlCon);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#PhoneBookID", parameters.PhoneBookId); //connecting each value to database
sqlCmd.Parameters.AddWithValue("#FirstName",parameters.FirstName);
sqlCmd.Parameters.AddWithValue("#LastName",parameters.LastName);
sqlCmd.Parameters.AddWithValue("#Contact",parameters.Contact);
sqlCmd.Parameters.AddWithValue("#Email", parameters.Email);
sqlCmd.Parameters.AddWithValue("#Address",parameters.Address);
sqlCmd.ExecuteNonQuery();
}
}
}
public class InsertUpdateContactParameters
{
public int PhoneBookId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Contact { get; set; }
public string Email { get; set; }
public string Address { get; set; }
}
As a first step you could create an instance of the SqlCommands class in your form, and then call InsertUpdateContact, passing in parameters populated from your form fields. That gets you to a point where you can create tests for your SQL code that you can execute without actually having to open your form, type in values, and press a button.
The test for your SQL code isn't technically a unit test because it talks to your database. It's an integration test. But it looks and functions just like a unit test. You're going to
Arrange - set something up
Act - execute your method
Assert - your test passes if the thing you expect happens, otherwise it fails.
For a real simple test, you could
Arrange - delete all records from your table that match some pattern, like the email address is "integrationtest#integrationtest.com" or the like.
Act - Call your method, passing in a set of values including the same email address that you just deleted.
Assert - Query your database to confirm that it contains a record matching the values you just inserted.
Cleanup - for good measure, run the delete again so you don't leave the testing record behind.
To make the inserts and deletions easier you could put a class in your unit test project something like this:
static class Sql
{
public static void ExecuteSql(string connectionName, string sql)
{
using (var connection = new SqlConnection(GetConnectionString(connectionName)))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
}
public static T ExecuteScalar<T>(string connectionName, string sql)
{
using (var connection = new SqlConnection(GetConnectionString(connectionName)))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
return (T)command.ExecuteScalar();
}
}
}
public static string GetConnectionString(string connectionName)
{
return ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
}
}
If you're using the .NET Framework, you could have an app.config file with a connection strings section like this:
<connectionStrings>
<add name="yourDatabaseName" connectionString="whatever your connection string is"
providerName="System.Data.SqlClient" />
</connectionStrings>
Or you could code it to retrieve your connection string according to however you're storing it.
That allows you to write code in your tests like
Sql.ExecuteSql("Your connection name", "SQL to delete records");
or
var numberOfInsertedRecords = Sql.ExecuteScalar<int>("Your connection name",
"SELECT COUNT(*) FROM Whatever WHERE ... "
+ "Replace with criteria that checks for the record you just inserted."
Then in your test you can say:
Assert.AreEqual(1, numberOfInsertedRecords);
Some other interesting areas you might like to read about are dependency injection, ORMs (like Entity Framework and NHibernate), and CQRS. That's a whole lot of stuff to pile on, but if you're just starting off writing a form and some SQL and you're already thinking about unit tests then the sky's the limit.
Here's a blog post I wrote about this a few years ago. It feels dated. I feel compelled to apologize for just about anything I've written more than a year or two ago.
Related
I have some code that looks like this (I have simplified it to focus on the issue, but the code is exactly as below with sensitive data names replaced):
private const string TargetIdParamName = "TargetId";
private const string LinkedGroupIdParamName = "LinkedGroupId";
private static readonly string UpdateLinkFromSql =
$#"UPDATE MyTableName
Set LinkFromId = :{LinkedGroupIdParamName}
WHERE Id = :{TargetIdParamName}";
using (var dbConn = GetConnection())
{
dbConn.Open();
using (var trans = dbConn.BeginTransaction())
{
try
{
var cmd = dbConn.CreateTransactedCommand(trans);
AddParameters(cmd);
cmd.CommandText = UpdateLinkFromSql;
cmd.Parameters[TargetIdParamName].Value = request.TargetGroupId;
cmd.Parameters[LinkedGroupIdParamName].Value = request.BreakPreviousLink ? DBNull.Value : (object) request.PreviousGroupId.Value;
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception e)
{
trans.Rollback();
throw;
}
}
}
private void AddParameters(OracleCommand cmd)
{
cmd.Parameters.Add(TargetIdParamName, OracleDbType.Long, ParameterDirection.Input);
cmd.Parameters.Add(LinkedGroupIdParamName, OracleDbType.Long, ParameterDirection.Input);
}
public static class DataAccessExtensions
{
public static OracleCommand CreateTransactedCommand(this OracleConnection source, OracleTransaction trans)
{
var cmd = source.CreateCommand();
cmd.Transaction = trans;
return cmd;
}
}
To illustrate the problem, lets say the 'TargetGroupId' was 12345 and the 'PreviousGroupId' was 67890.
From this code, I would expect the record with Id 12345 to have it's LinkFromId updated to 67890.
But what happens is the opposite, record with Id 67890 has it's LinkFromId set to 12345.
Now to get the expected behavior is easy, swap the values assigned to each parameter.
But the question remains, why are the parameters being swapped from what is expected? And yes I have triple checked that the query is what I think it is, the parameters are passed in correctly (like I did not accidentally name the parameters in the query in the opposite order or anything). Am I missing something?
Make sure you tell the command object to bind the parameters by name before executing it.
cmd.BindByName = true;
If you don't do this, it binds them ordinally. If they were added in the reverse order in which you were referring to them, that would explain the swapping.
I always set that property to true because the alternative is not as usable. It should be the default but that would be a breaking change. Fortunately, it's specific to the Oracle providers.
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.
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.
I have following code in a model that I have made to work with all DB related activities so I don’t get to write the redundant piece of code every time I want to work with the Database, this model class looks like this:
Shared.cs:
private static string ConStr
{
get
{
Shared shrObj = new Shared();
return shrObj.DecryptString(ConfigurationManager.ConnectionStrings["constr"].ConnectionString);
}
}
public static SqlConnection SqlCon = new SqlConnection(ConStr);
public static SqlDataReader ORC(SqlCommand sqlCom)
{
SqlDataReader sqlReader=null;
try
{
SqlCon.Open();//ERROR HERE
//The ConnectionString property has not been initialized.
sqlReader = sqlCom.ExecuteReader();
}
catch (Exception ex)
{
WriteToFile(DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") + " | " + ex, 0);
return sqlReader;
}
return sqlReader;
}
//Functions for closing connections…
//Functions for reading scalar…
//etc.
And now from other models when I try to use these function like this:
User.cs
internal IEnumerable<User> GetUser()
{
var sqlCom = new SqlCommand("SELECT * FROM [user];", Shared.SqlCon);
using (var blgs = Shared.ORC(sqlCom))
{
// ……. … …
}
}
}
One more thing that confusing me is when this data read function is called for first time from here while logging in, it works fine it’s always the second time call which creates problem.
May be I am just not playing write with static properties. But I have to keep it static because its being used by the SqlConnection object which itself is static to be used directly from outside the class.
Kindly help.
In a web app, it's usually better to open and close a connection via a using statement like so:
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
// do some stuff
}
Don't reuse a sqlconnection as it can lead to unexpected timeouts in your webapp.
I'm looking to figure out the best way to execute a database query using the least amount of boilerplate code. The method suggested in the SqlCommand documentation:
private static void ReadOrderData(string connectionString)
{
string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
}
}
finally
{
reader.Close();
}
}
}
mostly consists of code that would have to be repeated in every method that interacts with the database.
I'm already in the habit of factoring out the establishment of a connection, which would yield code more like the following. (I'm also modifying it so that it returns data, in order to make the example a bit less trivial.)
private SQLConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
private List<int> ReadOrderData()
{
using(var connection = CreateConnection())
using(var command = connection.CreateCommand())
{
command.CommandText = "SELECT OrderID FROM dbo.Orders;";
using(var reader = command.ExecuteReader())
{
var results = new List<int>();
while(reader.Read()) results.Add(reader.GetInt32(0));
return results;
}
}
}
That's an improvement, but there's still enough boilerplate to nag at me. Can this be reduced further? In particular, I'd like to do something about the first two lines of the procedure. I don't feel like the method should be in charge of creating the SqlCommand. It's a tiny piece of repetition as it is in the example, but it seems to grow if transactions are being managed manually or timeouts are being altered or anything like that.
edit: Assume, at least hypothetically, there's going to have to be a bunch of different types of data being returned. And consequently the solution can't be just one one-size-fits-all method, there will have to be a few different ones depending, at minimum, on whether ExecuteNonQuery, ExecuteScalar, ExecuteReader, ExecuteReaderAsync, or any of the others are being called. I'd like to cut down on the repetition among those.
Tried Dapper?
Granted this doesn't get you a DataReader but you might just prefer it this way once you've tried it.
It's about the lightest-weight an ORM can be while still being called an ORM. No more methods to map between DataReader and strong types for me.
Used right here on all the StackExchange sites.
using (var conn = new SqlConnection(cs))
{
var dogs = connection.Query("select name, age from dogs");
foreach (dynamic dog in dogs)
{
Console.WriteLine("{0} age {1}", dog.name, dog.age);
}
}
or
using (var conn = new SqlConnection(cs))
{
var dogs = connection.Query<Dog>("select Name, Age from dogs");
foreach (Dog dog in dogs)
{
Console.WriteLine("{0} age {1}", dog.Name, dog.Age);
}
}
class Dog
{
public string Name { get; set; }
public int Age { get; set; }
}
If you want to roll data access on your own, this pattern of help methods could be one way to remove duplication:
private List<int> ReadOrderData()
{
return ExecuteList<int>("SELECT OrderID FROM dbo.Orders;",
x => x.GetInt32("orderId")).ToList();
}
private IEnumerable<T> ExecuteList(string query,
Func<IDataRecord, T> entityCreator)
{
using(var connection = CreateConnection())
using(var command = connection.CreateCommand())
{
command.CommandText = query;
connection.Open();
using(var reader = command.ExecuteReader())
{
while(reader.Read())
yield return entityCreator(reader);
}
}
}
You'll have to add support for parameters and this might not compile, but the pattern is what I'm trying to illustrate.
What I typically do is use a custom class that I wrote a while back that accepts a SQL string, and optionally a list of parameters and it returns a DataTable.
Since the thing that changes between invocations is typically just the SQL that is optimal IMHO.
If you truly do need to use a DataReader you can do something like this:
public void ExecuteWithDataReader(string sql, Action<DataReader> stuffToDo) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
using (SqlCommand command = new SqlCommand(sql, connection)) {
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()) {
try {
while (reader.Read()) {
stuffToDo(reader);
}
}
finally {
reader.Close();
}
}
}
}
}
private static void ReadOrderData(string connectionString) {
string sql = "SELECT OrderID, CustomerID FROM dbo.Orders;";
ExecuteWithDataReader(sql, r => Console.WriteLine(String.Format("{0}, {1}", r[0], r[1])));
}
The first two line are the most important thing you need...
but if you still wish to do it, you can turn them to a database handler class, yes it will become more of code, but in refactoring concept, every thing will move to the related topic...
try to write a singleton class, that receive a command and do action, so return result of type SqlDataReader reader...
Doing this in comments was too much.
I would suggest that the boilerplate code around
using(conn = new sqlconnection)
using(cmd = new sqlcommand) {
// blah blah blah
}
isn't something to be lightly removed and instead would encourage that you keep it exactly where it's at. Resources, especially unmanaged ones, should be opened and released at the closest point to execution as possible IMHO.
In no small part due to the ease with which other developers will fail to follow the appropriate clean up conventions.
If you do something like
private SQLConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
Then you are inviting another programmer to call this method and completely fail to release the resource as soon as the query is executed. I don't know what kind of app you are building, but in a web app such a thing will lead to memory / connection / resource errors of types that are difficult to debug, unless you've been through it before.
Instead, I'd suggest you look into a lightweight ORM such as Dapper.net or similar to see how they approached it. I don't use dapper, but I hear it's pretty good. The reason I don't use it is simply that we don't allow inline sql to be executed against our databases (but that's a very different conversation).
Here's our standard:
public static DataTable StatisticsGet( Guid tenantId ) {
DataTable result = new DataTable();
result.Locale = CultureInfo.CurrentCulture;
Database db = DatabaseFactory.CreateDatabase(DatabaseType.Clients.ToString());
using (DbCommand dbCommand = db.GetStoredProcCommand("reg.StatsGet")) {
db.AddInParameter(dbCommand, "TenantId", DbType.Guid, tenantId);
result.Load(db.ExecuteReader(dbCommand));
} // using dbCommand
return result;
} // method::StatisticsGet
We make heavy use of Enterprise Library. It's short, simple and to the point and very well tested. This method just returns a datatable but you could easily have it return an object collection.. or nothing.