How do I handle Database Connections with Dapper in .NET?
Asked Answered
L

9

115

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 class, 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?

Leyla answered 9/2, 2012 at 21:12 Comment(2)
Too late but; I implemented it like this: https://mcmap.net/q/121094/-how-can-i-implement-the-unit-of-work-pattern-with-dapperCarbolated
using-dapper-asynchronously-in-asp-net-core-2 - exceptionnotfound.net/…Pliable
B
108

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 implements not only IDbConnection but also IComponent interface. So your custom interfaces won't be able to use just the SqlConnection implementation.

I also tried to create my own DbConnection class that takes different connection strings. That's too complicated because you have to implement all the methods from the DbConnection class. You lost the help from SqlConnection.

What I end up doing

  1. 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.
  2. I injected the dictionary as Singleton.
  3. Instead of injecting IDbConnection, I created IDbConnectionFactory and injected that as Transient for all repositories. Now all repositories take IDbConnectionFactory instead of IDbConnection.
  4. 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 helps.

Bin answered 21/11, 2017 at 1:13 Comment(9)
Exactly what i am searching for. I had the same problem and solved it in the same way, i still dont know if this is a good practice but, in my opinion, i think it is.Unpriced
Would it be better to register IDbConnection for IServiceProvider scope? One can create service and register as singleton scope factory with different connections and using var scope = factory.CreateNonDefaultScope(); using var connection = scope.ServiceProvider.GetRequiredService<IDbConnection>() you will get your non-default connection. Less inheritance will help with extensibility as well...Polemist
This is what I am looking for. Awsome job @David. ThanksPartlet
be cautious when you use this with having several async calls on db queries: here and here. this caused same strange troubles in my code.Retaliate
"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.Ashley
You are not using the using statement for connection disposal nor closing the connection at the end. Will it not create any problem ?Southwestward
@Sujoy: please see the comments @Ashley made. I guess I didn't read the Dapper docs clearly enough and thought Dapper will automatically open, close and dispose connections for me. Hence I didn't use using statement. But as what others have pointed out, it's almost never wrong to use using anyway.Bin
can a scoped instance depend on a Transient instance?Sylvia
@DavidLiang So would you please update the part where you said "No need to use using statement..." I was also confused about that until I randomly expanded the comment section and luckily I saw MarredCheese's comment, thanks for the helpful explanation btw!Flaky
I
34

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.

Inquiline answered 1/2, 2017 at 22:4 Comment(11)
BaseRepository is unnecessary inheritance since it doesn't provide any public or abstract methods or properties. This could instead be a DBHelper class.Cyrenaica
May be it is better to move CreateConnection to own class?Garlaand
May be... But personally I like to keep everything simple. If you have a lot of logic in CreateConnection(...) it may be a good idea. In my projects this method is as simple as "return new Connection(connectionString)", so it may be used inline without separate CreateConnection(...) method.Inquiline
Also, as nick-s pointed out, in the latest versions of Dapper you don't need to open database connection manually. Dapper will open it for you automatically. updated the post.Inquiline
inject it imo. services.AddScoped<IDbConnection>(p => new SqlConnection(connString) then just ask for it where neededDistrait
isn't this vialating dependency injection as well? Because you aren't using interfaces anymore. So if you want to go with repository pattern this is violating it.Retaliate
the question is about handling database connections and Dapper. Usually I use DI but I didn't want to overwhelm my response with anything not related to the question's main topic.Inquiline
BTW if we use some DI framework we don't always need to use interfaces. If we write unit tests and mock our repositories we need interfaces for sure. If not, we may use classes without interfaces. Also usually we don't need to use AddScoped or AddTransient because repositories do not have any state (not static variables) and we can use AddSingleton instead and save some CPU cycles for more useful work. (this part related to @FelixOuttaSpace comment)Inquiline
@PavelMelnikov how would you write a BaseRepository method for when you need multiple mapping. For example...connection.Query<TFirst, Second, TReturn>(this IdbConnection conn, string sql, Func<TFirst, Second, TReturn> map)Spall
@Spall after all the years working with dapper I still not found anything better than creating a base method for each combination of type parameters and optional field for field names that split the result set into entities (the same way as it is done in dapper). Usually there are three type params at most. at least I haven’t seen more than four.Inquiline
@PavelMelnikov so in your BaseRepository -- for multiple mapping methods -- do you also pass the Func from your concrete child classes to the BaseRepository? The Func cannot be abstract or generic as it tells Dapper how to materialize the object relationship. In other words, which property on the parent object should you store the associated child object. I imagine you have to create that Func in your child repository and pass that Func to the BaseRepository?Spall
S
31

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);
        }
    }
Smacking answered 11/6, 2012 at 13:28 Comment(5)
One question here. Since conn.Query returns IEnumerable<T> is it safe to immediately dispose of the connection object? Doesn't the IEnumerable need the connection in order to materialize the elements as they are read? Should we run a ToList()?Jacobine
I'd have to get back in to Dapper to verify, but I'm pretty sure i took this pattern as is from working production code. It should be okay - but of course, you should test any code on the internet.Smacking
If you are using a dapper Query extension method, you don't need to open the connection explicitly as it is done in the method itself.Betty
The issue with the above code is that if you pass in buffered: true to the Query method, the connection will dispose before the data is returned. Internally, Dapper will turn the enumerable into a list before returning.Epiphysis
@BrianVallelunga wouldn't that be buffered: false?Poilu
D
8

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;
});
Declamatory answered 12/2, 2016 at 15:1 Comment(2)
One question here. Since conn.Query returns Ienumerable<T> is it safe to immediately dispose of the connection? Doesn't the IEnumerable need the connection in order to materialize the elements as they are read?Jacobine
@AdrianNasui: Currently, Dapper's default behavior is to execute your SQL and buffer the entire reader on return, so the IEnumerable<T> is already materialized. If you pass buffered: false, yes, you will need to consume the output before exiting the using block.Argentina
S
7

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();
        }
    }
}
Sickly answered 10/2, 2012 at 4:17 Comment(1)
Isn't the OP asking more about the SqlConnection([[CONN STRING HERE]]) part? He says "But it feels wrong to me to reference a connection string in every class (even in each method)" I think he's wondering if us Dapper users have generated a pattern (of sorts) around wrapping the connection-creation side of things to DRY/hide that logic. (An aside to the OP, if you can use Dapper.Rainbow, do so ... it's really nice!)Continual
N
4

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;
        }

    }
Nate answered 28/3, 2012 at 14:48 Comment(2)
How do you handle closing / disposing the connection in your solution?Coeducation
@JPShook - I believe he's using using. (ref https://mcmap.net/q/157280/-in-a-quot-using-quot-block-is-a-sqlconnection-closed-on-return-or-exception)Snowbird
S
4

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;
      }
    }
  }
Synagogue answered 3/2, 2017 at 19:55 Comment(3)
This is really useful knowing that Dapper will leave the connection open if its already open when it gets it. I'm now pre-opening the db connection before I pass/use it with Dapper and I got a 6x performance gain - thanks!Pains
Transactions are created by connections, as in IDbTransaction tran = conn.BeginTransaction();. In your code, the wrapper creates its own connection. Therefore, the wrapper's transaction parameter is broken/misleading, no?Ashley
@Ashley I have not been using Dapper for a few years now. However, i believe when we were using this wrapper we were utilizing the TransactionScope similar to this discussion here - https://mcmap.net/q/119433/-how-to-use-transactions-with-dapper-net. Dapper *might be smart enough to wire together the transactions from multiple connections, but i am unsure of this. Here is the source - github.com/DapperLib/Dapper/blob/… best of luck.Synagogue
S
3

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.

Seraphim answered 23/3, 2018 at 16:27 Comment(0)
H
1

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.

Homicide answered 29/6, 2016 at 18:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.