In C# I am able to create a class like this:
static class clsDBUtils
{
public static SQLiteCommand cmd;
public static SQLiteConnection conn;
public static String databaseFilePath;
public static bool getConnection()
{
}
}
Then anywhere in my namespace can use without initialization this way:
clsDBUtils.getConnection();
How can this be rewritten for Java?
I don't want to use:
clsDBUtils sqlutil= new clsDBUtils();
Basically the same way, just make a (normal) final class with a private contructor (prevents being able to do new) and add static members only.
public final class clsDBUtils {
public static SQLiteCommand cmd;
public static SQLiteConnection conn;
public static String databaseFilePath;
public static bool getConnection() {
}
private clsDBUtils() {}
}
Apart from the particular question/problem, it is bad practice to declare expensive and external resources like Connection, Statement and ResultSet as an instance variable, let alone as a static variable. Those resources doesn't have an endless lifetime and your application may break when the DB decides to timeout the connection because it hasn't been released back to the DB after use.
I can't imagine that it's done differently in C# (it would have been a bug in the application as well), but the normal JDBC idiom is that you acquire and close it in the shortest possible scope, thus already inside the very same method block. E.g.
public Entity find(Long id) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
Entity entity = null;
try {
connection = database.getConnection();
statement = connection.prepareStatement(SQL_FIND);
statement.setLong(1, id);
resultSet = statement.executeQuery();
if (resultSet.next()) {
entity = new Entity();
entity.setProperty(resultSet.getObject("columnname"));
// etc..
}
} finally {
// Always free resources in reversed order.
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return entity;
}
The database.getConnection() can however technically perfectly be made static like this:
public final class Database {
static {
try {
Class.forName("com.example.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
private Database() {
// No need to instantiate this class.
}
public static Connection getConnection() {
DriverManager.getConnection("jdbc:example://localhost/dbname", "user", "pass");
}
}
so that you can use it as
connection = Database.getConnection();
(which you still really need to close in the finally block after use!)
However, this makes the connection source also really static. You cannot take benefit of polymorphism and/or inheritance anymore to switch between connection sources, such as a connection pool (to get better performance). To get more ideas/insights you may find this article useful
The code for it is almost exactly the same (same concept, slightly different syntax)
public class ClsDBUtils
{
public static SQLiteCommand cmd;
public static SQLiteConnection conn;
public static String databaseFilePath;
public static boolean getConnection()
{
}
}
// somewhere else
ClsDBUtils.getConnection();
Just declare a public class and use the 'static' modifier on your methods and fields. If you do not want it to be instantiated, use 'public final class '. Alternatively, you can use a singleton class.
You want to implement the Singleton pattern: http://en.wikipedia.org/wiki/Singleton_pattern
public class clsDBUtils {
private static final clsDBUtils INSTANCE = new clsDBUtils();
// Private constructor prevents instantiation from other classes
private clsDBUtils() {}
public static clsDBUtils getInstance() {
return INSTANCE;
}
public SQLiteCommand cmd;
public SQLiteConnection conn;
public String databaseFilePath;
public bool getConnection()
{
}
}
You can then use the following syntax on your class:
clsDBUtils.getInstance().getConnection();
Related
This is my code so far:
public class ServerUtility
{
public static int LogError(string source, string detail)
{
int iresult = -99;
try
{
BaseRepository repo = new BaseRepository();
using (SqlConnection con = new SqlConnection(repo.connectionString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand($"INSERT INTO [dbo].[LogError]([source],[detail],[date])VALUES('{source.Replace("'", "''")}','{detail.Replace("'", "''")}',GETDATE());SELECT ##IDENTITY", con))
{
string getValue = cmd.ExecuteScalar().ToString();
iresult = Convert.ToInt32(getValue);
} // command disposed here
} //connection closed and disposed here
}
catch (Exception ex) { throw ex; }
return iresult;
}
}
My question is on GetInstance method :
BaseRepository repo = new BaseRepository();
using (SqlConnection con = new SqlConnection(repo.connectionString))
I am always set it as new object, on my static function, just for get constant value from AppSetting.
What actually happened if I implement this code to my project?
How about the performance?
Is it cause performance issue?
Thanks
Like #gtosto mentioned, you're not implementing singletons correctly.
It should be:
public static SenderBackupProvider GetInstance()
{
if (oInstance == null)
{
oInstance = new SenderBackupProvider(CommFunction.GetLogNumber(CommonConst.APPID));
}
return oInstance;
}
Check out Implementing the Singleton Pattern in C#.
EDIT:
Since OP doesn't believe that the oInstance variable should be null on first time run, here's a screenshot.
Upon a closer look at your code, you are using a web application. The life cycle of static variables differ from one platform to the other. You might need to do an app domain restart in IIS. See more information in Lifetime of ASP.NET Static Variable.
What is the custom wen the record inserting/updating is carried out?
I have this Log table in the MS SQL server database, and a C# class (example is simplified)
[Table(Name = "dbo.Sys_Log")]
public class Sys_Log
{
// Read-only, db-generated primary key ID
private int _logID;
[Column(IsPrimaryKey=true, Storage="_logID", IsDbGenerated=true)]
public int logID
{
get
{
return this._logID;
}
}
// Read-only db-generated datetime field
private System.DateTime _logTime;
[Column(Storage="_logTime", IsDbGenerated=true)]
public System.DateTime logTime
{
get
{
return this._logTime;
}
}
// Read-write string field
private string _logEvent;
[Column(Storage="_logEvent")]
public string logEvent
{
get
{
return this._logEvent;
}
set
{
this._logEvent = value;
}
}
public Sys_Log() {}
public Sys_Log(string logEvent)
{
this.logEvent = logEvent;
}
}
And this is how I add a log entry:
Table<Sys_Log> linqLog = db.GetTable<Sys_Log>();
Sys_Log l = new Sys_Log("event");
linqLog.InsertOnSubmit(l);
db.SubmitChanges();
I am not particularly happy about this code. I'd like something like this instead:
Sys_Log.Log("event");
I have idea how this can be achieved, but I'd like to know if I am following the LINQ philosophy. With this code added to the Sys_Log class
private static DataContext db;
public static void Connect(DataContext db)
{
Sys_Log.db = db;
}
public static void Log(string logEvent)
{
Table<Sys_Log> linqLog = db.GetTable<Sys_Log>();
Sys_Log l = new Sys_Log(logEvent);
linqLog.InsertOnSubmit(l);
db.SubmitChanges();
}
I can now do this:
Sys_Log.Connect(db); // Only once, at init
Sys_Log.Log("event1");
Sys_Log.Log("event2");
Are there any pitfalls, apart from the fact that the database is updated several times, that could be considered ineffective?
************** Update ******************
Following the advice of #usr not to reuse the DataContext object, I have made these changes to the Sys_Log class:
private static SqlConnection db;
public static void Connect(SqlConnection db)
{
Sys_Log.db = db;
}
public static void Log(string logEvent)
{
DataContext ctx = new DataContext(db);
ctx.CommandTimeout = 240;
Table<Sys_Log> linqLog = ctx.GetTable<Sys_Log>();
Sys_Log l = new Sys_Log(logEvent);
linqLog.InsertOnSubmit(l);
ctx.SubmitChanges();
}
Use a fresh data context each time. Reusing the same context has to catastrophic consequences:
No entity memory is ever released
When an invalid entity enters the context (due to a bug) it is stuck and will forever prevent SubmitChanges from succeeding. The application will never recover
Also note, that L2S is deprecated and EF has superseded it.
You can share a SqlConnection and use it long-term if you really want. That requires, through, that you deal with broken connections. Thanks to connection pooling there are little performance incentives to do this.
It usually is the easiest and most clear way to use throw-away connections. Inject a factory, for example:
Func<SqlConnection> myFactory = () => new SqlConnection(myConnStr);
That's all there is to it. Use it, as always, with using:
using(var conn = myFactory()) { ... }
I am busy developing a class library project in C# to be reused and attached to different projects in future. It will mainly be used for Table Valued Parameters. My question is, how do I pass a SQL connection to it? The connection will be instantiated in another (main project) that the .dll gets attached to.
I currently have a Class Library Project, and have a Console Application Project created in the same solution for testing purposed.
One last requirement is that I don't want to use ConfigurationManager as the connection string will not be stored in app.config or web.config and by default the queries must be passed back to the calling application.
I've come accross a couple of links like the one below, but nothing I can really use:
Sharing a connection string
Please excuse the noobness, I am 7 weeks into professional programming.
In your dll, simply require an IDbConnection or IDbCommand. All the method is then properly abstracted against the interfaces for the data access.
For example:
In your shared dll
public static int LookUpIntForSomething(IDbConnection connection)
{
using (var command = connection.CreateCommand())
{
// use command.
}
}
In your calling app
using (var connection = new SqlConnection("ConnectionString"))
{
var int = DbQueries.LookupIntForSomething(connection);
}
This is excellent example for dependency injection. I would recommend using enterprise library unity for this kind of stuff. In your data access layer library I would define interface:
public interface IConnectionProvider {
string ConnectionString { get; }
}
public interface IAccountProvider {
Account GetAccountById(int accountID);
}
internal class AccountProvider : IAccountProvider {
private IConnectionProvider _connectionProvider;
public AccountProvider(IConnectionProvider connectionProvider) {
if (connectionProvider == null) {
throw new ArgumentNullException("connectionProvider");
}
_connectionProvider = connectionProvider;
}
public Account GetAccountById(int accountID) {
Account result;
using(var conn = new SqlConnection(connectionProvider)) {
// retrieve result here
}
return result;
}
}
public static class Bootstrapper {
public static void Init() {
ServiceLocator.AddSingleton<IAccountProvider, AccountProvider>();
}
}
Then in any assembly using your data access library you can define implementation for IConnectionProvider, like this:
internal class WebConnectionProvider : IConnectionProvider {
public string ConnectionString { get { return "Server=..."; } }
}
internal static class WebBootstrapper {
public static void Init() {
Bootstrapper.Init();
ServiceLocator.AddSingleton<IConnectionProvider, WebConnectionProvider>();
}
}
And anywhere after you call WebBootstrapper.Init() in your assembly you can use:
var accountProvider = ServiceLocator.Resolve<IAccountProvider>();
accountProvider.GetAccountById(1);
Service locator:
using System;
using Microsoft.Practices.Unity;
public class ServiceLocator {
private IUnityContainer m_Container = new UnityContainer();
public void Add<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>();
}
public void BuildUp<T>(T instance) {
m_Container.BuildUp<T>(instance);
}
public void BuildUp(Type type, object instance) {
m_Container.BuildUp(type, instance);
}
public void AddSingleton<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager());
}
public void AddInstance<T>(T instance) {
m_Container.RegisterInstance<T>(instance);
}
public T Resolve<T>() {
return m_Container.Resolve<T>();
}
private static ServiceLocator m_Instance;
public static ServiceLocator Instance {
get { return m_Instance; }
}
static ServiceLocator() {
m_Instance = new ServiceLocator();
}
}
if i understand your requirements correctly,I'm not sure that i do, i would setup a static struct as such
public static struct ConnectionString
{
public int ID;
public string Connection;
public override string ToString()
{
return Connection;
}
public static ConnectionString DataBase1 = new ConnectionString{ ID = 1 , Connection = "YourConnectionStringhere"};
public static ConnectionString DataBase2 = new ConnectionString{ ID = 2 , Connection = "YourConnectionString2here"};
}
and then use it as such
public void SomeMethod()
{
var I = ReferencedDll.DoSomething(ConnectionString.DataBase1.ToString());
}
or
public void SomeMethod()
{
var ClassFromDll = new ReferencedDll.SomeClass(ConnectionString.DataBase1.ToString());
ClassFromDll.DoSomething();
}
of course this leaves your connection strings hard coded which is not ideal
First of all I read this on an article - which basically tells me I should not be using a singleton at all -
Most commonly, singletons don't allow any parameters to be specified when creating the instance - as otherwise a second request for an instance but with a different parameter could be problematic! (If the same instance should be accessed for all requests with the same parameter, the factory pattern is more appropriate.)
Since I need parameters, and same instances with same parameters - I concluded I need a factory pattern.
But I was unable to find a good factory pattern implementation anywhere.
Kindly direct me if you find any good c# singleton factory pattern implementation with parameters
Ok I am going to try and be very specific here... hope this explains my situation.
Alternate methods are most welcome. I just combined a lot of implementations - my understanding may be off.
So I have a class 'A'. It is a class used to connect to a database - Database connection.
The connection needs 4 parameters & the constraints are:
I need to have multiple connections possible - with different databases (parameters differ)
I need only 1 instance of a specific connection - a singleton with parameters which are same (in my understanding)
I will need a factory model as per the article mentioned above and also to limit the number of connections, close the connection after a timeout etc.
On this basis I need a singleton factory with paramenters/arguements... I assume
So the class A is going to look something like this
<which access modifier ?> Class A {
private Class A(string hostname, string port, string username, string pw_hash) {
//create a new instance with the specified parameters
}
//other methods on the connection
protected void close() {
//close the connection
}
}
public class AFactory//should it inherit class A?? {
private IList<A> connections = new List<A>();
private AFactory()
{
//do something
}
private static readonly Lazy<AFactory> lazy
= new Lazy<AFactory>(() => new AFactory());
public static AFactory Instance { get { return lazy.Value; } }
public A getA(string hostname, string service, string username, string pw_hash)
{
foreach (A a in A)
{
if (a.hostname == hostname && a.service == service && a.username == username)
return a;
}
A d = new A(hostname, service, username, pw_hash);
connections.Add(d);
return d;
}
Now this works well and good as long as the class A constructor is public - but It kind of defeats the purpose of a singleton.
What do I need to do to get this code to work.
I need only 1 instance of class A for the specified parameters.
Thanks
Indrajit
Factory is used to generate object rather than manage object. I think a DB connection manager is more suitable in your situation. You can declare the manager as singleton. For individual connection you can use internal class/struct.
See below example:
class DBConnectionManager
{
struct Connection
{
public string Hostname;
public string ServerName;
public string UserName;
public string Password;
public void Connect()
{
}
public void Close()
{
}
}
private static s_instance;
public static DBConnectionManager Instance
{
get {return s_instance; }
}
private List<Connection> m_connections;
public Connection GetConnection(string hostname, string serverName, string userName, string password)
{
// if already exist in m_connections
// return the connection
// otherwise create new connection and add to m_connections
}
public void CloseConnection(string hostname, string serverName, string userName, string password)
{
// if find it in m_connections
// then call Close()
}
public void CloseAll()
{
//
}
}
So I have done this and it works... can you tell me if it is correct. And also is it Thread-Safe?
public Class A
{
private A(string hostname, string port, string username, string pw_hash) {
//create a new instance with the specified parameters
}
//other methods on the connection
protected void close() {
//close the connection
}
public class AFactory
{
private IList<A> connections = new List<A>();
private AFactory()
{
//do something
}
private static readonly Lazy<AFactory> lazy
= new Lazy<AFactory>(() => new AFactory());
public static AFactory Instance { get { return lazy.Value; } }
public A getA(string hostname, string service, string username, string pw_hash)
{
foreach (A a in connections)
{
if (a.hostname == hostname && a.service == service && a.username == username)
return a;
}
A d = new A(hostname, service, username, pw_hash);
connections.Add(d);
return d;
}
}
}
I am using it like this:
A.AFactory fact = A.AFactory.Instance;
A conn = fact.getA(a, b, c, d);
A conn2 = fact.getA(e, f, g, h);
Is there something glaringly wrong with this implementation?
you could try this:
public static class Singlett<Param,T>
where T : class
{
static volatile Lazy<Func<Param, T>> _instance;
static object _lock = new object();
static Singlett()
{
}
public static Func<Param, T> Instance
{
get
{
if (_instance == null)
{
_instance = new Lazy<Func<Param, T>>(() =>
{
lock (Singlett<Param,T>._lock)
{
try
{
ConstructorInfo constructor = null;
Type[] methodArgs = { typeof(Param) };
constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, methodArgs, null);// Binding flags excludes public constructors.
if (constructor == null)
{
constructor = typeof(T).GetConstructor(BindingFlags.Public, null, methodArgs, null);
if (constructor == null)
return delegate(Param o) { return (T)Activator.CreateInstance(typeof(T), new object[] { o }); };
}
return delegate(Param o) { return (T)constructor.Invoke(new object[] { o }); };
}
catch (Exception exception)
{
throw exception;
}
}
});
}
return _instance.Value;
}
}
}
then to use it:
instead of
int i = 10;
MyClass class = new MyClass(i);
you can write:
int i = 10;
MyClass class = Singlett<int,MyClass>.Instance(i);
Try this:
This interface is exposed from the factory initializer and contains the exposed methods and properties.
public interface IDatabase
{
string ConnectionString { get; set; }
IDataReader ExecuteSql(string sql);
}
Factory base abstract class where you can perform common features to different types of database factories.
public abstract class FactoryBase
{
public FactoryBase() { }
public abstract IDatabase GetDataLayer();
}
Concrete sql class that contains your calls. Have a look at the ExecuteSql method. The connection is self contained in the command so you don't have to worry about opening and closing and disposing of it.
public class SQL : IDatabase
{
private string m_ConnectionString = string.Empty;
public string ConnectionString
{
get { return m_ConnectionString; }
set { m_ConnectionString = value; }
}
public IDataReader ExecuteSql(string sql)
{
using (var command = new SqlCommand(sql, new SqlConnection(ConnectionString)) { CommandType = CommandType.Text, CommandText = sql, CommandTimeout = 0 })
{
if (command.Connection.State != ConnectionState.Open) command.Connection.Open();
return command.ExecuteReader();
}
}
}
Sql factory class that creates an instance of the Sql concrete class.
class SQLFactory : FactoryBase
{
public override IDatabase GetDataLayer()
{
return new SQL();
}
}
The factory initializer class that a developer will use to pass in a type of factory and it will return the IDatabase.
public static class FactoryInitializer
{
public static IDatabase LoadFactory<T>(string connectionstring) where T : FactoryBase, new()
{
var factory = new T();
var data = factory.GetDataLayer();
data.ConnectionString = connectionstring;
return data;
}
}
Then use it as:
var factory = FactoryInitializer.LoadFactory<SQLFactory>(connectionString);
factory.ExecuteSql("SELECT ...");
You can then create may be an OracleFactory and an Oracle concrete class and use it the same way.
I've been playing with Dapper, but I'm not sure of the best way to handle the database connection.
Most examples show the connection object being created in the example class, or even in each method. But it feels wrong to me to reference a connection string in every clss, even if it's pulling from the web.config.
My experience has been with using a DbDataContext or DbContext with Linq to SQL or Entity Framework, so this is new to me.
How do I structure my web apps when using Dapper as my Data Access strategy?
Update: clarification from MarredCheese's comment:
"No need to use a using statement. Dapper will automatically open,
close, and dispose of the connection for you." That's not correct.
Dapper will automatically open closed connections, and it will
automatically close connections that it auto-opened, but it will not
automatically dispose of connections. Marc Gravell and Eric Lippert
both advocate using using with Dapper here.
Microsoft.AspNetCore.All: v2.0.3 | Dapper: v1.50.2
I am not sure if I am using the best practices correctly or not, but I am doing it this way, in order to handle multiple connection strings.
It's easy if you have only 1 connection string
Startup.cs
using System.Data;
using System.Data.SqlClient;
namespace DL.SO.Project.Web.UI
{
public class Startup
{
public IConfiguration Configuration { get; private set; }
// ......
public void ConfigureServices(IServiceCollection services)
{
// Read the connection string from appsettings.
string dbConnectionString = this.Configuration.GetConnectionString("dbConnection1");
// Inject IDbConnection, with implementation from SqlConnection class.
services.AddTransient<IDbConnection>((sp) => new SqlConnection(dbConnectionString));
// Register your regular repositories
services.AddScoped<IDiameterRepository, DiameterRepository>();
// ......
}
}
}
DiameterRepository.cs
using Dapper;
using System.Data;
namespace DL.SO.Project.Persistence.Dapper.Repositories
{
public class DiameterRepository : IDiameterRepository
{
private readonly IDbConnection _dbConnection;
public DiameterRepository(IDbConnection dbConnection)
{
_dbConnection = dbConnection;
}
public IEnumerable<Diameter> GetAll()
{
const string sql = #"SELECT * FROM TABLE";
// No need to use using statement. Dapper will automatically
// open, close and dispose the connection for you.
return _dbConnection.Query<Diameter>(sql);
}
// ......
}
}
Problems if you have more than 1 connection string
Since Dapper utilizes IDbConnection, you need to think of a way to differentiate different database connections.
I tried to create multiple interfaces, 'inherited' from IDbConnection, corresponding to different database connections, and inject SqlConnection with different database connection strings on Startup.
That failed because SqlConnection inherits from DbConnection, and DbConnection inplements not only IDbConnection but also Component class. So your custom interfaces won't be able to use just the SqlConnection implenentation.
I also tried to create my own DbConnection class that takes different connection string. That's too complicated because you have to implement all the methods from DbConnection class. You lost the help from SqlConnection.
What I end up doing
During Startup, I loaded all connection string values into a dictionary. I also created an enum for all the database connection names to avoid magic strings.
I injected the dictionary as Singleton.
Instead of injecting IDbConnection, I created IDbConnectionFactory and injected that as Transient for all repositories. Now all repositories take IDbConnectionFactory instead of IDbConnection.
When to pick the right connection? In the constructor of all repositories! To make things clean, I created repository base classes and have the repositories inherit from the base classes. The right connection string selection can happen in the base classes.
DatabaseConnectionName.cs
namespace DL.SO.Project.Domain.Repositories
{
public enum DatabaseConnectionName
{
Connection1,
Connection2
}
}
IDbConnectionFactory.cs
using System.Data;
namespace DL.SO.Project.Domain.Repositories
{
public interface IDbConnectionFactory
{
IDbConnection CreateDbConnection(DatabaseConnectionName connectionName);
}
}
DapperDbConenctionFactory - my own factory implementation
namespace DL.SO.Project.Persistence.Dapper
{
public class DapperDbConnectionFactory : IDbConnectionFactory
{
private readonly IDictionary<DatabaseConnectionName, string> _connectionDict;
public DapperDbConnectionFactory(IDictionary<DatabaseConnectionName, string> connectionDict)
{
_connectionDict = connectionDict;
}
public IDbConnection CreateDbConnection(DatabaseConnectionName connectionName)
{
string connectionString = null;
if (_connectDict.TryGetValue(connectionName, out connectionString))
{
return new SqlConnection(connectionString);
}
throw new ArgumentNullException();
}
}
}
Startup.cs
namespace DL.SO.Project.Web.UI
{
public class Startup
{
// ......
public void ConfigureServices(IServiceCollection services)
{
var connectionDict = new Dictionary<DatabaseConnectionName, string>
{
{ DatabaseConnectionName.Connection1, this.Configuration.GetConnectionString("dbConnection1") },
{ DatabaseConnectionName.Connection2, this.Configuration.GetConnectionString("dbConnection2") }
};
// Inject this dict
services.AddSingleton<IDictionary<DatabaseConnectionName, string>>(connectionDict);
// Inject the factory
services.AddTransient<IDbConnectionFactory, DapperDbConnectionFactory>();
// Register your regular repositories
services.AddScoped<IDiameterRepository, DiameterRepository>();
// ......
}
}
}
DiameterRepository.cs
using Dapper;
using System.Data;
namespace DL.SO.Project.Persistence.Dapper.Repositories
{
// Move the responsibility of picking the right connection string
// into an abstract base class so that I don't have to duplicate
// the right connection selection code in each repository.
public class DiameterRepository : DbConnection1RepositoryBase, IDiameterRepository
{
public DiameterRepository(IDbConnectionFactory dbConnectionFactory)
: base(dbConnectionFactory) { }
public IEnumerable<Diameter> GetAll()
{
const string sql = #"SELECT * FROM TABLE";
// No need to use using statement. Dapper will automatically
// open, close and dispose the connection for you.
return base.DbConnection.Query<Diameter>(sql);
}
// ......
}
}
DbConnection1RepositoryBase.cs
using System.Data;
using DL.SO.Project.Domain.Repositories;
namespace DL.SO.Project.Persistence.Dapper
{
public abstract class DbConnection1RepositoryBase
{
public IDbConnection DbConnection { get; private set; }
public DbConnection1RepositoryBase(IDbConnectionFactory dbConnectionFactory)
{
// Now it's the time to pick the right connection string!
// Enum is used. No magic string!
this.DbConnection = dbConnectionFactory.CreateDbConnection(DatabaseConnectionName.Connection1);
}
}
}
Then for other repositories that need to talk to the other connections, you can create a different repository base class for them.
using System.Data;
using DL.SO.Project.Domain.Repositories;
namespace DL.SO.Project.Persistence.Dapper
{
public abstract class DbConnection2RepositoryBase
{
public IDbConnection DbConnection { get; private set; }
public DbConnection2RepositoryBase(IDbConnectionFactory dbConnectionFactory)
{
this.DbConnection = dbConnectionFactory.CreateDbConnection(DatabaseConnectionName.Connection2);
}
}
}
using Dapper;
using System.Data;
namespace DL.SO.Project.Persistence.Dapper.Repositories
{
public class ParameterRepository : DbConnection2RepositoryBase, IParameterRepository
{
public ParameterRepository (IDbConnectionFactory dbConnectionFactory)
: base(dbConnectionFactory) { }
public IEnumerable<Parameter> GetAll()
{
const string sql = #"SELECT * FROM TABLE";
return base.DbConnection.Query<Parameter>(sql);
}
// ......
}
}
Hope all these help.
It was asked about 4 years ago... but anyway, maybe the answer will be useful to someone here:
I do it like this in all the projects.
First, I create a base class which contains a few helper methods like this:
public class BaseRepository
{
protected T QueryFirstOrDefault<T>(string sql, object parameters = null)
{
using (var connection = CreateConnection())
{
return connection.QueryFirstOrDefault<T>(sql, parameters);
}
}
protected List<T> Query<T>(string sql, object parameters = null)
{
using (var connection = CreateConnection())
{
return connection.Query<T>(sql, parameters).ToList();
}
}
protected int Execute(string sql, object parameters = null)
{
using (var connection = CreateConnection())
{
return connection.Execute(sql, parameters);
}
}
// Other Helpers...
private IDbConnection CreateConnection()
{
var connection = new SqlConnection(...);
// Properly initialize your connection here.
return connection;
}
}
And having such a base class I can easily create real repositories without any boilerplate code:
public class AccountsRepository : BaseRepository
{
public Account GetById(int id)
{
return QueryFirstOrDefault<Account>("SELECT * FROM Accounts WHERE Id = #Id", new { id });
}
public List<Account> GetAll()
{
return Query<Account>("SELECT * FROM Accounts ORDER BY Name");
}
// Other methods...
}
So all the code related to Dapper, SqlConnection-s and other database access stuff is located in one place (BaseRepository). All real repositories are clean and simple 1-line methods.
I hope it will help someone.
I created extension methods with a property that retrieves the connection string from configuration. This lets the callers not have to know anything about the connection, whether it's open or closed, etc. This method does limit you a bit since you're hiding some of the Dapper functionality, but in our fairly simple app it's worked fine for us, and if we needed more functionality from Dapper we could always add a new extension method that exposes it.
internal static string ConnectionString = new Configuration().ConnectionString;
internal static IEnumerable<T> Query<T>(string sql, object param = null)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
return conn.Query<T>(sql, param);
}
}
internal static int Execute(string sql, object param = null)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
return conn.Execute(sql, param);
}
}
I do it like this:
internal class Repository : IRepository {
private readonly Func<IDbConnection> _connectionFactory;
public Repository(Func<IDbConnection> connectionFactory)
{
_connectionFactory = connectionFactory;
}
public IWidget Get(string key) {
using(var conn = _connectionFactory())
{
return conn.Query<Widget>(
"select * from widgets with(nolock) where widgetkey=#WidgetKey", new { WidgetKey=key });
}
}
}
Then, wherever I wire-up my dependencies (ex: Global.asax.cs or Startup.cs), I do something like:
var connectionFactory = new Func<IDbConnection>(() => {
var conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["connectionString-name"];
conn.Open();
return conn;
});
Best practice is a real loaded term. I like a DbDataContext style container like Dapper.Rainbow promotes. It allows you to couple the CommandTimeout, transaction and other helpers.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Dapper;
// to have a play, install Dapper.Rainbow from nuget
namespace TestDapper
{
class Program
{
// no decorations, base class, attributes, etc
class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime? LastPurchase { get; set; }
}
// container with all the tables
class MyDatabase : Database<MyDatabase>
{
public Table<Product> Products { get; set; }
}
static void Main(string[] args)
{
var cnn = new SqlConnection("Data Source=.;Initial Catalog=tempdb;Integrated Security=True");
cnn.Open();
var db = MyDatabase.Init(cnn, commandTimeout: 2);
try
{
db.Execute("waitfor delay '00:00:03'");
}
catch (Exception)
{
Console.WriteLine("yeah ... it timed out");
}
db.Execute("if object_id('Products') is not null drop table Products");
db.Execute(#"create table Products (
Id int identity(1,1) primary key,
Name varchar(20),
Description varchar(max),
LastPurchase datetime)");
int? productId = db.Products.Insert(new {Name="Hello", Description="Nothing" });
var product = db.Products.Get((int)productId);
product.Description = "untracked change";
// snapshotter tracks which fields change on the object
var s = Snapshotter.Start(product);
product.LastPurchase = DateTime.UtcNow;
product.Name += " World";
// run: update Products set LastPurchase = #utcNow, Name = #name where Id = #id
// note, this does not touch untracked columns
db.Products.Update(product.Id, s.Diff());
// reload
product = db.Products.Get(product.Id);
Console.WriteLine("id: {0} name: {1} desc: {2} last {3}", product.Id, product.Name, product.Description, product.LastPurchase);
// id: 1 name: Hello World desc: Nothing last 12/01/2012 5:49:34 AM
Console.WriteLine("deleted: {0}", db.Products.Delete(product.Id));
// deleted: True
Console.ReadKey();
}
}
}
Try this:
public class ConnectionProvider
{
DbConnection conn;
string connectionString;
DbProviderFactory factory;
// Constructor that retrieves the connectionString from the config file
public ConnectionProvider()
{
this.connectionString = ConfigurationManager.ConnectionStrings[0].ConnectionString.ToString();
factory = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[0].ProviderName.ToString());
}
// Constructor that accepts the connectionString and Database ProviderName i.e SQL or Oracle
public ConnectionProvider(string connectionString, string connectionProviderName)
{
this.connectionString = connectionString;
factory = DbProviderFactories.GetFactory(connectionProviderName);
}
// Only inherited classes can call this.
public DbConnection GetOpenConnection()
{
conn = factory.CreateConnection();
conn.ConnectionString = this.connectionString;
conn.Open();
return conn;
}
}
Everyone appears to be opening their connections entirely too early? I had this same question, and after digging through the Source here - https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper/SqlMapper.cs
You will find that every interaction with the database checks the connection to see if it is closed, and opens it as necessary. Due to this, we simply utilize using statements like above without the conn.open(). This way the connection is opened as close to the interaction as possible. If you notice, it also immediately closes the connection. This will also be quicker than it closing automatically during disposal.
One of the many examples of this from the repo above:
private static int ExecuteCommand(IDbConnection cnn, ref CommandDefinition command, Action<IDbCommand, object> paramReader)
{
IDbCommand cmd = null;
bool wasClosed = cnn.State == ConnectionState.Closed;
try
{
cmd = command.SetupCommand(cnn, paramReader);
if (wasClosed) cnn.Open();
int result = cmd.ExecuteNonQuery();
command.OnCompleted();
return result;
}
finally
{
if (wasClosed) cnn.Close();
cmd?.Dispose();
}
}
Below is a small example of how we use a Wrapper for Dapper called the DapperWrapper. This allows us to wrap all of the Dapper and Simple Crud methods to manage connections, provide security, logging, etc.
public class DapperWrapper : IDapperWrapper
{
public IEnumerable<T> Query<T>(string query, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
using (var conn = Db.NewConnection())
{
var results = conn.Query<T>(query, param, transaction, buffered, commandTimeout, commandType);
// Do whatever you want with the results here
// Such as Security, Logging, Etc.
return results;
}
}
}
I wrap connection with the helper class:
public class ConnectionFactory
{
private readonly string _connectionName;
public ConnectionFactory(string connectionName)
{
_connectionName = connectionName;
}
public IDbConnection NewConnection() => new SqlConnection(_connectionName);
#region Connection Scopes
public TResult Scope<TResult>(Func<IDbConnection, TResult> func)
{
using (var connection = NewConnection())
{
connection.Open();
return func(connection);
}
}
public async Task<TResult> ScopeAsync<TResult>(Func<IDbConnection, Task<TResult>> funcAsync)
{
using (var connection = NewConnection())
{
connection.Open();
return await funcAsync(connection);
}
}
public void Scope(Action<IDbConnection> func)
{
using (var connection = NewConnection())
{
connection.Open();
func(connection);
}
}
public async Task ScopeAsync<TResult>(Func<IDbConnection, Task> funcAsync)
{
using (var connection = NewConnection())
{
connection.Open();
await funcAsync(connection);
}
}
#endregion Connection Scopes
}
Examples of usage:
public class PostsService
{
protected IConnectionFactory Connection;
// Initialization here ..
public async Task TestPosts_Async()
{
// Normal way..
var posts = Connection.Scope(cnn =>
{
var state = PostState.Active;
return cnn.Query<Post>("SELECT * FROM [Posts] WHERE [State] = #state;", new { state });
});
// Async way..
posts = await Connection.ScopeAsync(cnn =>
{
var state = PostState.Active;
return cnn.QueryAsync<Post>("SELECT * FROM [Posts] WHERE [State] = #state;", new { state });
});
}
}
So I don't have to explicitly open the connection every time.
Additionally, you can use it this way for the convenience' sake of the future refactoring:
var posts = Connection.Scope(cnn =>
{
var state = PostState.Active;
return cnn.Query<Post>($"SELECT * FROM [{TableName<Post>()}] WHERE [{nameof(Post.State)}] = #{nameof(state)};", new { state });
});
What is TableName<T>() can be found in this answer.
Hi #donaldhughes I'm new on it too, and I use to do this:
1 - Create a class to get my Connection String
2 - Call the connection string class in a Using
Look:
DapperConnection.cs
public class DapperConnection
{
public IDbConnection DapperCon {
get
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["Default"].ToString());
}
}
}
DapperRepository.cs
public class DapperRepository : DapperConnection
{
public IEnumerable<TBMobileDetails> ListAllMobile()
{
using (IDbConnection con = DapperCon )
{
con.Open();
string query = "select * from Table";
return con.Query<TableEntity>(query);
}
}
}
And it works fine.