I have a console application with a base class as following:
public abstract class PaymentSystemBase : IPayable
{
private SqlConnection _connection;
protected PaymentSystemBase()
{
CreateDatabaseConnection();
}
protected void CreateDatabaseConnection()
{
if(_connection == null)
{
string connectionString = ConfigurationManager.AppSettings["connString"];
var connection = new SqlConnection(connectionString);
_connection = connection;
connection.Open();
}
}
public SqlConnection Connection
{
get { return _connection; }
}
public abstract void ProcessPayment();
}
And have a few classes that derive from PaymentSystemBase:
public class PS1 : PaymentSystemBase
{
public override void ProcessPayment()
{
// Work with database using Connection from PaymentSystemBase
}
}
public class PS2 : PaymentSystemBase
{
public override void ProcessPayment()
{
// Work with database using Connection from PaymentSystemBase
}
}
In main program:
var lstPayments = new List<IPayable>
{
new PS1(),
new PS2()
};
var processPayments = new ProcessPayments(lstPayments);
processPayments.Process();
Where:
public class ProcessPayments
{
private List<IPayable> _paymentSystems;
public ProcessPayments(List<IPayable> paymentSystem)
{
_paymentSystems = paymentSystem;
}
public void Process()
{
foreach (var paymentSystem in _paymentSystems)
{
paymentSystem.ProcessPayment();
}
}
}
My question is how to use the same connection from PaymentSystemBase class and close it after processing? As I can see the connection was created again every time when PS1 and PS2 were created.
You shouldn't try to share the connection object. The connection objects themselves are actually quite lightweight, being an abstraction built on top of the actual physical connections, that the ADO.NET connection pool takes care of creating.
So you base class should be something like:
public abstract class PaymentSystemBase : IPayable
{
private static string _connectionString =
ConfigurationManager.ConnectionStrings["connString"].ConnectionString
public static string ConnectionString
{
get { return _connection; }
}
public abstract void ProcessPayment();
}
And then your derived classes should be:
public class PS1 : PaymentSystemBase
{
public override void ProcessPayment()
{
using(var conn = new SqlConnection(PaymentSystemBase.ConnectionString))
{
using(var cmd = new SqlCommand("...",conn)
{
//Prepare command
conn.Open();
cmd.ExecuteXXX();
//Process results, etc
}
}
}
}
You'll notice that I've also switched where the connection string is loaded from via the ConfigurationManager class from AppSettings to ConnectionStrings, which is a dedicated part of the configuration system for storing connection strings. This wasn't actually required but it is more conventional.
Related
I have a class library that contains hundreds of static methods and variable as follows…
public class General
{
public static string Con { get; set; }
public static string Func1()
{
using (SqlConnection con = new SqlConnection(Con))
{
// My stuff here
}
}
public static string Func2()
{
using (SqlConnection con = new SqlConnection(Con))
{
// My stuff here
}
}
public static string Funcn()
{
using (SqlConnection con = new SqlConnection(Con))
{
// My stuff here
}
}
}
I referenced this class library to my ASP.Net Webform app and assign connectionstring from Global.asax’s Application_Start event
protected void Application_Start(object sender, EventArgs e)
{
General.Con = ConfigurationManager.ConnectionStrings["Con"].ConnectionString;
}
Everything works fine.
Now that I wanted to change database connectionstring on per-LoggedIn-user basis.
What I have tried:
I stored all user’s connectionstring info at one table in common database and mapped them to respective userIDs.
On Login button click, I could save connectionstring to session.
Session["Con"] = ds.Tables[0].Rows[0][0].ToString();
In class library I used
Public static string Con = System.Web.HttpContext.Current.Session["Con"].ToString();
I get error : Object reference not set to an instance of an object.
If I remove static, all my variable and methods gives an error: An object reference is required for the non-static
If I use new keyword here, error is “Cannot be accessed with an instance reference; qualify it with a type name instead”.
Then I used
public static string Con()
{
string Con = "";
HttpContext httpContext = HttpContext.Current;
if (httpContext.ApplicationInstance.Session.Count > 0)
{
if (httpContext.ApplicationInstance.Session["Con"] != null)
Consd = httpContext.ApplicationInstance.Session["Con"].ToString();
}
return Con;
}
It gives me error: Cannot convert from method group to string
Please help me out…
Your class is static, which means there is a single instance, yet you want to change the connection on a user basis.
That is obviously not going to work. I would personally recommend you allow multiple instances of your class (non-static) and initialize each instance with the connection string as a parameter:
public class General
{
private string _connectionString;
public General(string connectionString)
{
_connectionString = connectionString;
}
}
You can then instantiate it once per session if you want, or simply instantiate it every time you need to use it. I would not recommend adding dependencies into the class (e.g. where the connection string comes to).
var data = new General(ds.Tables[0].Rows[0][0].ToString());
var result = data.Func1();
If for some reason, you need to keep the class static, you would need to either provide the connection string to the function so it can use it, or embed the logic to pull out the connection string from the session into the method:
public static string Func1(string connectionString)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
// My stuff here
}
}
OR
public static string Func1()
{
using (SqlConnection con = new SqlConnection(ds.Tables[0].Rows[0][0].ToString()))
{
// My stuff here
}
}
I would recommend passing the connection string as a parameter if you decide to go this route.
One last option if you wish to keep your class static would be to use a Configurator object that provides the connection string, in order to abstract the location:
public interface IConfigurator
{
string GetConnectionString();
}
public class SessionConfigurator : IConfigurator
{
public string GetConnectionString()
{
var connectionString = Session["Con"].ToString();
return connectionString;
}
}
public static class General
{
public IConfigurator Configurator { get; set; }
public static string Func1()
{
using (SqlConnection con = new SqlConnection(Configurator.GetConnectionString()))
{
// My stuff here
}
}
}
Then upon application startup:
General.Configurator = new SessionConfigurator();
I have 40 suppliers that need to make an ftp connection, do something there and close the connection. So, all of those 40 suppliers have their own class and they all have the connection and disconnection of the ftp server, but they all have different processing methods.
So basically I have 40 classes with this method:
ftp.Connect();
//do something - this is different for all the classes
ftp.Close();
So the do something part is different for all, it does different things, it uses different variables, etc.
What I thought I would do is: create a new class that would be instantiated in all the 40 suppliers. This class will have one method that look something like this:
public void Connect(FTPCredentials credentials, Process process)
{
var ftp = new FtpConnection(credentials.Host, credentials.Username, credentials.Password);
ftp.Open();
ftp.Login();
process(ftp);
ftp.Close();
}
public delegate void Process(FtpConnection ftp/*, string name*/);
The problem I have here is that all the methods in all 40 suppliers have different input parameters so what would the input parameters of Process be? Also, I think I don't gain much because I still have the FtpConnection ftp parameter here which means that I will have to add the dll that has the class FtpConnection in every project that will use the Connect method.
For example, the process method in the suppliers would look like this:
process(string fileName) //and it would download fileName
process(string folderName) //create folder if it doesnt exist
Is there a design pattern I can use here that would be cleaner and would make things easier?
My impression is that such an object is used only shortly and for a single specific purpose. So I would accept specific parameters to be stored in a specific derived class. Similar to mybirthname's solution, I'd start with an abstract class, but define it differently:
public abstract class BaseSupplier
{
protected BaseSupplier(FtpCredentials credentials)
{
_Credentials = credentials;
}
private FtpCredentials _Credentials;
public void Run()
{
Connect();
Process();
Disconnect();
}
private void Connect() {/* your connection and login code */}
private void Disconnect() {/* your disconnect code */}
protected abstract void Process(); // to be filled in the derived class
}
public class ConcreteSupplier
{
public ConcreteSupplier(FtpCredentials credentials, SomeType parameter) : base(credentials)
{ /* store extra parameters */ }
override Process() {/*your concrete processing code */ }
}
If I remember correctly, That's called the Strategy Pattern.
Edit:
juunas is right, it's the Template Method pattern. In Gamma et al., Template Method is described directly after Strategy in the chapter on Behavioral Patterns.
Create abstract class
public abstract class BaseSupplier
{
public void Connect(FTPCredentials credentials, Process process, SupplierSettingClass settings)
{
var ftp = new FtpConnection(credentials.Host, credentials.Username, credentials.Password);
ftp.Open();
ftp.Login();
DoSomething(settings);
ftp.Close();
}
public virtual void DoSomething(SupplierSettingClass settings)
{
//define base case;
}
}
You need to create SupplierSettingClass in which you will implement every input parameter for DoSomething method as property (folderName, fieldName and so on)
public class SupplierSettingClass
{
public string FolderName {get; set;}
//and so on;
}
In the end in the SupplierA
public class SupplierA:BaseSupplier
{
public override void DoSomething(SupplierSettingClass settings)
{
//Do specific stuff for your class.
}
}
You can use some clever inheritance to contain pretty much all of the required behaviour in one base abstract class, like this:
public interface IProcessor
{
void Process(Credentials credentials);
}
public class Credentials
{
public string Host { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
public abstract class SupplierBase : IProcessor, IDisposable
{
protected FtpConnection _Connection;
private void Connect(Credentials credentials)
{
//Create the ftp connection
_Connection = new FtpConnection(credentials.Host, credentials.Username, credentials.Password);
_Connection.Open();
_Connection.Login();
}
private void Disconnect()
{
//Close and dispose the ftp connection
_Connection.Close();
_Connection.Dispose();
_Connection = null;
}
public void Process(Credentials credentials)
{
Connect(credentials);
Execute();
Disconnect();
}
protected abstract void Execute();
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
#endregion
}
public void MySupplier : SupplierBase
{
//You can add unique supplier properties here.
public string SomeProperty { get; set; }
protected override void Execute()
{
//Implementation here
Console.WriteLine(SomeProperty);
}
}
Here's an example of how you would call it:
Credentials creds = new Credentials()
{
Host = "127.0.0.1",
Username = "test",
Password = "test"
};
MySupplier sup1 = new MySupplier();
sup1.SomeProperty = "Hello";
sup1.Process(creds);
OR
using (MySupplier sup1 = new MySupplier())
{
sup1.SomeProperty = "Hello";
sup1.Process(creds);
}
I have a WPF Project which is n-tier architecture and I use context per/call as it has Direct-database and web-service
Sorry a bit long question
Presentation => Business Layer => Data Layer
In datalayer i have UnitOfWork pattern implemented.
Initally when my DefaultAccessPoint was a Static property i had issues on multiple thread using the same context.
I had resolved it by changing the DefaultAccessPoint to a non-static property, and seems that multi thread issue had been Resolved .
after the fix =>(e.g) User could insert data into the Application on First tab(which takes approx. 3 mins) and simultaneously access the Second Tab(To fetch some data) while both are done in separate threads.
But after this Fix the Context doesn't refresh when a modification is done
The initial fix was done under DataProviderBase class were i changed static DataAccessPoint to Non-static and commented those lines that you see below.
How would i keep the context refresh with multi threading ?
Any Help is appreciated
Code Block
This is my dataproviderbaseclass every data-provider is inherited this base
public abstract class DataProviderBase
{
public DataProviderBase()
{
DefaultAccessPoint = new DataAccessAccessPoint(ConnectionString);
}
protected readonly ILogger logger = LoggerFactory.GetLogger();
private static string _connectionString;
public static string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
//COMMENTED as Fix for multiThreading
//_defaultAccessPoint = new DataAccessAccessPoint(ConnectionString);
}
}
private IDataAccessAccessPoint _defaultAccessPoint;
public IDataAccessAccessPoint DefaultAccessPoint
{
get
{
//COMMENTED as Fix for multi Threading
// Removed statis Default AccessPoint that was causing the issue
return _defaultAccessPoint; //?? (_defaultAccessPoint = new DataAccessAccessPoint(ConnectionString));
}
set { _defaultAccessPoint = value; }
}
}
This is my DataAccessPoint
public class DataAccessAccessPoint : IDataAccessAccessPoint
{
private string _connectionString;
public string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
}
}
private IDataContext context;
public DataAccessAccessPoint(string connectionString)
{
_connectionString = connectionString;
context = new MyDataContext(_connectionString);
}
public virtual bool Save()
{
return context.SaveChanges() > 0;
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//Here i supply the context to my Data access layers
private IMyDataLayerDA _myDA;
public IMyDataLayerdDA MydDA
{
get { return _myDA ?? (_myDA = new MydDA(context)); }
set { _myDA = value; }
}
}
My DataProvider
public class PersonRoleDataProvider : DataProviderBase, IPersonRoleDataProvider
{
public MYDTOCLASS AuthenticateUser(string userId)
{
return DefaultAccessPoint.MydDA.AuthenticateUser(userId);
}
public IEnumerable<MYDTOCLASS> GetRoles(int personId)
{
return DefaultAccessPoint.MydDA.GetRoles(personId);
}
}
DataProviderAccessPoint
public class DataProviderAccessPoint
{
private static PersonRoleDataProvider _personRoleDataProvider;
public static PersonRoleDataProvider PersonRoleDataProvider
{
get
{
if(_personRoleDataProvider==null)
_personRoleDataProvider = new PersonRoleDataProvider();
return _personRoleDataProvider;
}
}
}
Here's my proposed (very simplified to illustrate the problem space) design for a C# console application. The database connections implement IDisposable, and this solution doesn't allow for using the database connection objects. Can someone propose a more correct structure for a console application? This is a problem I need to solve often.
class Program
{
SQLiteConnection sourceConnection;
SQLiteConnection destinationConnection;
static void Main(string[] args)
{
Program shell = new Program();
// get connection strings from command line arguments
string sourceConnectionString = shell.getConnectionString(args);
string destinationConnectionString = shell.getConnectionString(args);
// call non-static methods that use
shell.setUpConnections(sourceConnectionString, destinationConnectionString);
shell.doDatabaseWork();
}
private void setUpConnections(string sourceConnectionString, string destinationConnectionString)
{
sourceConnection = new SQLiteConnection(sourceConnectionString);
destinationConnection = new SQLiteConnection(destinationConnectionString);
}
private void doDatabaseWork()
{
// use the connections here
}
}
Edit:
Some people can't figure out why I'd want them as member variables. Here's my use case (a little psuedocoded) of what would go in doDatabaseWork:
foreach (Row sourceRow in DBResultSet)
{
string sourceXml = sourceRow.Columns["MyColumnName"].Value;
string destinationXML = transformUsingXSLT(sourceXml);
writeToDestination(destinationXml);
}
See how I'd want to keep these connections open for the life of this loop?
How about writing a class that implements IDisposable.
Inside your class constructor, you can instantiate your DB connections.
Then inside your IDisposable.Dispose Method, you write your tear down code for closing your DB connections.
Here is a code sample to demonstrate what I mean:
public class DBWrapper : IDisposable
{
public SqlConnection Connection1 { get; set; }
public SqlConnection Connection2 { get; set; }
public DBWrapper()
{
Connection1 = new SqlConnection();
Connection1.Open();
Connection2 = new SqlConnection();
Connection2.Open();
}
public void DoWork()
{
// Make your DB Calls here
}
public void Dispose()
{
if (Connection1 != null)
{
Connection1.Dispose();
}
if (Connection2 != null)
{
Connection2.Dispose();
}
}
}
And then, from within your main method of your Program class:
class Program
{
static void Main(string[] args)
{
using (DBWrapper wrapper = new DBWrapper())
{
wrapper.DoWork();
}
}
}
I think that the best solution is to extract main logic from Program class. The Program class is some kind of starter for primary work. And providing wrappers for SqlConnections is not a good idea indeed, because they are managed resources already, wrapping them is redundant. Thus my solution looks like this:
class ProgramCore : IDisposable
{
internal ProgramCore(string sourceConnectionString, string destinationConnectionString)
{
setUpConnections(sourceConnectionString, destinationConnectionString);
}
internal void Execute()
{
// do whatever you want
doDatabaseWork();
// do whatever you want
}
public void Dispose()
{
if (_sourceConnection != null)
_sourceConnection.Dispose();
if (_destinationConnection != null)
_destinationConnection.Dispose();
}
private void setUpConnections(string sourceConnectionString, string destinationConnectionString)
{
_sourceConnection = new SQLiteConnection(sourceConnectionString);
_destinationConnection = new SQLiteConnection(destinationConnectionString);
}
private void doDatabaseWork()
{
// use the connections here
}
private SQLiteConnection _sourceConnection;
private SQLiteConnection _destinationConnection;
}
class Program
{
static void Main(string[] args)
{
// get connection strings from command line arguments
string sourceConnectionString = GetConnectionString(args);
string destinationConnectionString = GetConnectionString(args);
using (ProgramCore core = new ProgramCore(sourceConnectionString, destinationConnectionString))
{
core.Execute();
}
}
static string GetConnectionString(string[] args)
{
// provide parsing here
}
}
Scott's answer is one way to do it. You could also consider using try{} finally instead?
static void Main(string[] args)
{
Program shell = new Program();
// get connection strings from command line arguments
string sourceConnectionString = shell.getConnectionString(args);
string destinationConnectionString = shell.getConnectionString(args);
// call non-static methods that use
shell.setUpConnections(sourceConnectionString, destinationConnectionString);
try
{
shell.doDatabaseWork();
}
finally
{
if(sourceConnection != null)
sourceConnection.Dispose();
if(destinationConnection != null)
destinationConnection.Dispose();
}
}
Personally, I think you are over thinking this and the code samples in this thread are overly complex imho. I have no idea why people are implementing IDisposable on their Program class either since it's disposed when it exits.
I can't think of a single reason to not use or why you cannot use the using(){} statement.
You want to open a Connection and hold it? Why? All the real connections are behind the scenes in .net connection pooling, so new'ing Connection objects is not a big deal. Just open and close as you need them and connection pooling handles all that behind the scenes.
I edited my example to wrap it in a class so you can have your encapsulation as well.
class Program
{
static void Main(string[] args)
{
DBWorker worker = new DBWorker();
worker.DoDatabaseWork();
}
}
public class DBWorker
{
private void DoDatabaseWork()
{
using (SQLiteConnection sourceDB = new SQLiteConnection( GetConnectionString() ))
{
sourceDB.Open();
using (SQLiteConnection destDB = new SQLiteConnection( GetConnectionString() ))
{
destDB.Open();
}
}
}
}
Hmm, I see no one has mentioned doing it this way. You don't have to have the variables that are used in the using declared locally.
class Program
{
SQLiteConnection sourceConnection;
SQLiteConnection destinationConnection;
static void Main(string[] args)
{
Program shell = new Program();
// get connection strings from command line arguments
string sourceConnectionString = shell.getConnectionString(args);
string destinationConnectionString = shell.getConnectionString(args);
using (sourceConnection = new SQLiteConnection(sourceConnectionString))
using (destinationConnection = new SQLiteConnection(destinationConnectionString))
{
shell.doDatabaseWork();
}
}
private void doDatabaseWork()
{
// use the connections here
}
}
My class has the following core:
class SmartDbConnection
{
private readonly IDbConnection Connection;
public SmartDbConnection(string ConnectionString)
{
if(ConnectionString.Contains("MultipleActiveResultSets=true"))
{
Connection = new SqlConnection(ConnectionString);
}
}
}
I don't want it to have "SqlConnection" hardcoded. So I thought in making it a Generic class (accepting IDbConnection classes). But I don't know how to do it. Anyone can help?
First - I've added IDisposable to this, as I believe it is important.
Second, note that providers are an alternative here:
class SmartDbConnection
{
private DbConnection Connection;
public SmartDbConnection(string provider, string connectionString)
{
Connection = DbProviderFactories.GetFactory(provider)
.CreateConnection();
Connection.ConnectionString = connectionString;
}
public void Dispose() {
if (Connection != null)
{
Connection.Dispose();
Connection = null;
}
}
}
If you must go generic, how about:
class SmartDbConnection<T> : IDisposable where T : class,
IDbConnection, new()
{
private T Connection;
public SmartDbConnection(string connectionString)
{
T t = new T();
t.ConnectionString = connectionString;
// etc
}
public void Dispose() {
if (Connection != null)
{
Connection.Dispose();
Connection = null;
}
}
}
Why don't you accept IDbConnection instead of connectionstring to your ctor?
Maybe...
class SmartDbConnection<T> where T : IDbConnection, new()
{
private readonly IDbConnection Connection;
public SmartDbConnection(string connectionString)
{
if (connectionString.Contains("MultipleActiveResultSets=true"))
{
Connection = new T();
Connection.ConnectionString = connectionString;
}
}
}
EDIT: But what kaanbardak suggests can be even better...
If you don't want to specify SqlConnection there, where would you specify it - and how would you know to use it only if the connection string contains "MultipleActiveResultSets=true"?
I suspect at some level you want a connection factory - either a Func<string, IDbConnection> you can pass in or set somewhere, or possibly just a class:
public static class ConnectionFactory
{
public static IDbConnection CreateConnection(string connectionString)
{
// Hard-code stuff here
}
}
Of course, they're just two sides of the same coin - ConnectionFactory is just a static implementation of the Func<string, IDbConnection>.
class SmartDbConnection<T> where T: IDbConnection , new()
{
private readonly T Connection;
public SmartDbConnection(string ConnectionString)
{
if (ConnectionString.Contains("MultipleActiveResultSets=true"))
{
Connection = new T();
Connection.ConnectionString = ConnectionString;
}
}
}