How to access static methode when its in class - c#

Here I write some code in static methode which is in class file please Help me how can i create instance of static class
public class ConnectionString
{
public static void CreateCommand(string querystring, string connectionString)
{
using(SqlConnection cn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(querystring, cn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
}

Just call it like this:
string querystring = "Your values here";
string connectionString = "Your values here";
ConnectionString.CreateCommand(querystring, connectionString);
That's it.

Your ConnectionString class can be refactored to implement an interface like this:
public interface IDataAccess
{
void CreateCommand(string querystring, string connectionString);
}
this interface allows us to inject its implementation in the controller that you mentioned in the comments. So your ConnectionString class (renamed to more meaningful name DataAccess) should look like this:
public class DataAccess : IDataAccess
{
public void CreateCommand(string querystring, string connectionString)
{
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand(querystring, cn))
{
cmd.ExecuteNonQuery();
}
}
}
}
then in your controller / client class you can have the concrete implementation injected at the run time..
public class DataController : Controller
{
private readonly IDataAccess dataAccess;
public DataController(IDataAccess dataAcces)
{
this.dataAccess = dataAcces;
}
public ActionResult ShowData()
{
string querystring = "you t-sql query";
string connectionString = "<you sql connection string>";
this.dataAccess.CreateCommand(querystring, connectionString);
return this.View();
}
}
If you are using MVC and dont know how to resolve the dependencies then refer to this article
Alternatively you can just new up the instance of DataAccess class like this:
public class DataController : Controller
{
private readonly IDataAccess dataAccess;
public DataController()
{
this.dataAccess = new DataAccess();
}
public ActionResult ShowData()
{
string querystring = "you t-sql query";
string connectionString = "<you sql connection string>";
this.dataAccess.CreateCommand(querystring, connectionString);
return this.View();
}
}
I will not recommend this approach as it wont be possible to unit test it.
Hope this helps!

Related

Can't insert data into database with ASP.NET/C#

I've been trying to create a simple registration page and connecting it with database, but when I click on the button to register a new user it returns the following message:
at MappingDatabase.Connection () [0x00016] in <bea5b5103c9f4cfba42ba460a8c4180f>:0
at PersonDatabase.Insert (Person p) [0x00002] in <bea5b5103c9f4cfba42ba460a8c4180f>:0
Here's the code:
using System.Data;
using MySql.Data.MySqlClient;
using System.Configuration;
public static class MappingDatabase
{
public static IDbConnection Connection()
{
MySqlConnection connection = new MySqlConnection(ConfigurationManager.AppSettings["databaseConnection"]);
connection.Open();
return connection;
}
public static IDbCommand Command(string sqlQuery, IDbConnection connection)
{
IDbCommand runCommand = connection.CreateCommand();
runCommand.CommandText = sqlQuery;
return runCommand;
}
public static IDbDataAdapter Adapter(IDbCommand command)
{
IDbDataAdapter adapter = new MySqlDataAdapter();
adapter.SelectCommand = command;
return adapter;
}
public static IDbDataParameter Parameter(string parameterName, object value)
{
return new MySqlParameter(parameterName, value);
}
}
public static class PersonDatabase
{
public static int Insert(Person p)
{
try
{
IDbConnection dbConnection = MappingDatabase.Connection();
IDbCommand dbCommand;
string sql = #"INSERT INTO PER_PERSON VALUES(0, ?name, ?email, ?password);";
dbCommand = MappingDatabase.Command(sql, dbConnection);
dbCommand.Parameters.Add(MappingDatabase.Parameter("?name", p.Name));
dbCommand.Parameters.Add(MappingDatabase.Parameter("?email", p.Email));
dbCommand.Parameters.Add(MappingDatabase.Parameter("?password", p.Password));
dbCommand.ExecuteNonQuery();
dbConnection.Close();
dbCommand.Dispose();
dbConnection.Dispose();
return 0;
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
return -1;
}
}
}
Here's the repository on GitHub
It worked before on a computer running Windows 10.
Could it be a problem with the connector file (MySql.Data.dll)? How can I fix that?
Note: I use Linux Ubuntu 20.04
You can fix this error by downloading the right connector in the hyperlink below:
Download Connector

Trouble mocking SqlConnection for Unit Tests

I am calling code that I cannot change that takes in a SqlConnection and a Transaction created from that SqlConnection. I am attempting to mock this SqlConnection using Moq 4.16.1. I am getting the following error when attempting to unit test the code:
Unable to cast object of type 'Castle.Proxies.IDbConnectionProxy' to type 'System.Data.SqlClient.SqlConnection'.
I have wrapped the SqlConnection in my own wrapper to try to get this to work, but this has not helped.
SqlConnectionWrapper:
using System.Data;
using System.Data.SqlClient;
namespace Wrappers
{
public class SQLConnectionWrapper : ISQLConnectionWrapper
{
public string ConnectionString { get; private set; }
public SQLConnectionWrapper(string connectionString)
{
ConnectionString = connectionString;
}
public IDbConnection Open()
{
return new SqlConnection(ConnectionString);
}
}
}
Unit test:
private Mock<ISQLConnectionWrapper> _mockSqlConnectionWrapper;
[SetUp]
public void Setup()
{
_mockSqlConnectionWrapper = new Mock<ISQLConnectionWrapper>();
var mockSQLConnection = new Mock<IDbConnection>();
mockSQLConnection.SetupAllProperties();
_mockSqlConnectionWrapper.Setup(x => x.Open())
.Returns(mockSQLConnection.Object);
}
Any help with this would be greatly appreciated.

Call void function inside of controller

I have following controller:
public ActionResult delete(int id)
{
//call function
return RedirectToAction("Index");
}
here I want to call following function from my model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MySql.Data.MySqlClient;
namespace project1.Models.Admin
{
public class delete
{
public void delete(int id)
{
//xxx
const string ConnStr = "...";
MySqlConnection connection = new MySqlConnection(ConnStr);
connection.Open();
MySqlCommand sqlcmd2;
sqlcmd2 = connection.CreateCommand();
sqlcmd2.CommandText = "UPDATE `user` SET Aktive = 0 WHERE Nr = #id;";
sqlcmd2.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
sqlcmd2.ExecuteNonQuery();
connection.Close();
//xxx
}
}
}
I get the error that "void" isn't allowed in this context. Is there any other way to call my function here or should I put the whole connection (inside "xxx") into my controller?
Change method name;
public void deleteFunc(int id)
EDIT
Firstly, you should be careful about naming convention. I change your class name like DeleteAction and method name DeleteRecord
public class DeleteAction
{
public void DeleteRecord(int id)
{
//xxx
const string ConnStr = "...";
MySqlConnection connection = new MySqlConnection(ConnStr);
connection.Open();
MySqlCommand sqlcmd2;
sqlcmd2 = connection.CreateCommand();
sqlcmd2.CommandText = "UPDATE `user` SET Aktive = 0 WHERE Nr = #id;";
sqlcmd2.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
sqlcmd2.ExecuteNonQuery();
connection.Close();
//xxx
}
}
Then, you can call desired function by creating an instance from class;
public ActionResult delete(int id)
{
var deleteActionObject = new DeleteAction();
deleteActionObject.DeleteRecord(id);
return RedirectToAction("Index");
}
There are several problems in your code.
First you cannot use delete as both a class- and a member-name. Having said this delete is a really bad name for a class.
Second you should follow naming-conventions, e.g. use PascalCase-names for both methods and classes.
And last and most important, you need an instance of your class of which you want to call the method:
public ActionResult delete(int id)
{
myInstanceOfDeleteClass.delete(id);
return RedirectToAction("Index");
}
If you donĀ“t have an instance of that class, you may also make delete a static one. Then you could directly call the method within your controller:
public ActionResult delete(int id)
{
DeleteClass.Delete(id);
return RedirectToAction("Index");
}
public class DeleteClass
{
public static void Delete(int id)
{
//xxx
const string ConnStr = "...";
MySqlConnection connection = new MySqlConnection(ConnStr);
connection.Open();
MySqlCommand sqlcmd2;
sqlcmd2 = connection.CreateCommand();
sqlcmd2.CommandText = "UPDATE `user` SET Aktive = 0 WHERE Nr = #id;";
sqlcmd2.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
sqlcmd2.ExecuteNonQuery();
connection.Close();
//xxx
}
}

Dependency Injection and Connection Factory

I am trying to use DI with Factory. What I have so far is:
Factory:
public interface IConnectionFactory
{
IDbConnection Create();
}
public class DbConnectionFactory : IConnectionFactory
{
private readonly DbProviderFactory _providerFactory;
private readonly string _connectionString;
public DbConnectionFactory(string connectionString, string providerName)
{
_connectionString = connectionString;
_providerFactory = DbProviderFactories.GetFactory(providerName);
}
public IDbConnection Create()
{
var connection = _providerFactory.CreateConnection();
if (connection != null)
connection.ConnectionString = _connectionString;
return connection;
}
}
public class DbContext
{
private readonly IDbConnection _connection;
public DbContext(IConnectionFactory connectionFactory)
{
_connection = connectionFactory.Create();
}
public IDbCommand CreateCommand()
{
var cmd = _connection.CreateCommand();
return cmd;
}
public void Dispose()
{
_connection.Dispose();
}
}
public static class DbCommandExtensions
{
public static IDbDataParameter CreateParameter(this IDbCommand command, string name, object value)
{
var parameter = command.CreateParameter();
parameter.ParameterName = name;
parameter.Value = value;
return parameter;
}
}
Repository:
public class AgentRepository : IAgentRepository
{
private readonly DbContext _context;
public AgentRepository(DbContext context)
{
_context = context;
}
public bool Exists(string input)
{
using (var command = _context.CreateCommand())
{
command.Connection.Open();
command.CommandType = CommandType.Text;
command.CommandText = #"";
command.Parameters.Add(command.CreateParameter("#input", input));
return (bool)command.ExecuteScalar();
}
}
}
Now, in my client application I would like to pass connection string down to repository. Connection string will be created dynamically from other data source. I also would like to have service layer which pulls data from repository and passes DTO to the client. As DI container I am using Ninject. My question is how client should be implemented and how should configure Factory in Ninject?
-- EDIT 1
To move my project forward I implemented an anti pattern:
Service:
public AgentService(string connectionString)
{
var connectionFactory = new DbConnectionFactory(connectionString, "System.Data.SqlClient");
var context = new DbContext(connectionFactory);
_agentRepository = new AgentRepository(context);
}
Client:
var connectionString = _systemService.GetConnectionString(ip);
var agentService = new AgentService(connectionString);
var exists = agentService.Exists(input);
I know that this is not best practice but I wasn't able to implement it using DI. Please let me know how can I refactor this piece of code as I am going to implement the same for over 30 classes.
-- EDIT 2
I've did dome refactoring and end up with:
// Client:
var connectionString = _systemService.GetConnectionString(ip);
var dbConnectionFactory = new DbConnectionFactory(connectionString, "System.Data.SqlClient");
var agentService = new AgentService(dbConnectionFactory);
var exists = agentService.AgentExists(input);
// Service:
public class AgentService : IAgentService
{
private readonly IAgentRepository _agentRepository;
public AgentService(IDbConnectionFactory connectionFactory)
{
var context = new DbContext(connectionFactory);
_agentRepository = new AgentRepository(context);
}
public bool AgentExists(string input)
{
return _agentRepository.AgentExists(input);
}
}
// Repository:
public class AgentRepository : IAgentRepository
{
private readonly DbContext _context;
public AgentRepository(DbContext context)
{
_context = context;
}
public bool AgentExists(string input)
{
using (var command = _context.CreateCommand())
{
command.Connection.Open();
command.CommandType = CommandType.Text;
command.CommandText = #"";
command.Parameters.Add(command.CreateParameter("#param", input));
return (bool)command.ExecuteScalar();
}
}
}
// Connection Factory:
public class DbConnectionFactory : IDbConnectionFactory
{
private readonly DbProviderFactory _provider;
private readonly string _connectionString;
public DbConnectionFactory(string connectionString, string providerName)
{
_provider = DbProviderFactories.GetFactory(providerName);
_connectionString = connectionString;
}
public IDbConnection Create()
{
var connection = _provider.CreateConnection();
if (connection != null)
connection.ConnectionString = _connectionString;
return connection;
}
}
// DbContext:
public class DbContext
{
private readonly IDbConnection _connection;
public DbContext(IDbConnectionFactory connectionFactory)
{
_connection = connectionFactory.Create();
}
public IDbCommand CreateCommand()
{
var cmd = _connection.CreateCommand();
return cmd;
}
public void Dispose()
{
_connection.Dispose();
}
}
I wonder if it would be possible to replace new operators in Service class with dependency injection. If it is possible how should it be configured using Ninject?

Mocking data access Layer Rhino mock

How can i mock data access layer using Rhino mocks
I have the following classes:
public interface IDataAccess
{
int ExecuteNoneQuery(SqlConnection connection, string storedProcedureName,
IEnumerable<SqlParameter> sqlParameters);
}
public class DataAccess : IDataAccess
{
public int ExecuteNoneQuery(SqlConnection connection, string storedProcedureName,
IEnumerable<SqlParameter> sqlParameters)
{
using (SqlCommand command = connection.CreateCommand())
{
// do some stuff
return command.ExecuteNonQuery();
}
}
}
public class DbOperation<T>
{
private IDataAccess _access;
public DbOperation(IDataAccess access)
{
_access = access;
}
public int Insert(T item, SqlConnection connection,string spName)
{
IDbObjectFactory<T> parametersFactory = new SqlParameterFactory<T>();
var parameters = (IList<SqlParameter>)parametersFactory.GetDbObject(item);
return _access.ExecuteNoneQuery(connection, spName, parameters);
}
}
Here is an example with some explanations:
To test the case:
WHEN method ExecuteNoneQuery of class DataAccess is called
THEN command.ExecuteNonQuery() should be called:
// 1. Create `SqlCommand` Mock:
var command = MockRepository.GenerateMock<SqlCommand>();
// 2. Create `SqlConnection` Stub:
var connection = MockRepository.GenerateStub<SqlConnection>();
// 3. Setup connection.CreateCommand() to return mocked command:
connection
.Stub(c => c.CreateCommand())
.Return(command);
// 4. Do test action:
var dataAccess = new DataAccess();
dataAccess.ExecuteNoneQuery(connection, null, null);
// Assert command.ExecuteNonQuery() has been called:
command.AssertWasCalled(c => c.ExecuteNonQuery());
Hope that explains a bit how to use Rhino Mock.
I assume you want to test DbOperation by mocking DataAccess.
public void TestInsert()
{
var dataAccess = MockRepository.GenerateMock<IDataAccess>();
var dbOperation = new DbOperation<string>(dataAccess);
var sqlConnection = new SqlConnection();
dbOperation.Insert("blah", sqlConnection, "MySP");
dataAccess.AssertWasCalled(a => a.ExecuteNoneQuery(
Arg.Is(sqlConnection),
Arg.Is("MySP"),
Arg<IEnumerable<SqlParameter>>.Is.Anything));
}
Ideally, you may want to even inject IDbObjectFactory<T> so that you can test the interaction between DbOperation and the sqlParameterFactory - and hence you could also check that ExecuteNoneQuery was called with the exact parameters that sqlParameterFactory would return.

Categories