मैं .NET में डैपर के साथ डेटाबेस कनेक्शन्स को कैसे संभालूँ?


86

मैं डैपर के साथ खेल रहा हूं, लेकिन डेटाबेस कनेक्शन को संभालने का सबसे अच्छा तरीका मुझे यकीन नहीं है।

अधिकांश उदाहरण उदाहरण कक्षा में, या यहां तक ​​कि प्रत्येक विधि में बनाए जा रहे कनेक्शन ऑब्जेक्ट को दर्शाते हैं। लेकिन यह मेरे लिए गलत है कि मैं हर क्लॉस में एक कनेक्शन स्ट्रिंग का संदर्भ देता हूं, भले ही वह web.config से खींच रहा हो।

मेरा अनुभव एक का उपयोग कर के साथ कर दिया गया है DbDataContextया DbContextएसक्यूएल या इकाई की रूपरेखा के लिए Linq के साथ है, तो यह मेरे लिए नया है।

मैं अपने डेटा एक्सेस रणनीति के रूप में डैपर का उपयोग करते समय अपने वेब एप्लिकेशन को कैसे तैयार करूं?


बहुत देर से लेकिन; मैंने इसे इस तरह से कार्यान्वित किया: stackoverflow.com/a/45029588/5779732
अमित जोशी

उपयोग-डॅपर-एसिंक्रोनसली-इन-एस्प-नेट-कोर -2 - अपवाद
हिमालया गर्ग

जवाबों:


53

Microsoft.AspNetCore.All : v2.0.3 | डैपर : v1.50.2

मुझे यकीन नहीं है कि मैं सही तरीके से सर्वोत्तम प्रथाओं का उपयोग कर रहा हूं या नहीं, लेकिन कई कनेक्शन स्ट्रिंग्स को संभालने के लिए, मैं इसे इस तरह से कर रहा हूं ।

यदि आपके पास केवल 1 कनेक्शन स्ट्रिंग है तो यह आसान है

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

        // ......
    }
}

यदि आपके पास 1 से अधिक कनेक्शन स्ट्रिंग हैं तो समस्याएं

चूंकि Dapperउपयोग करता है IDbConnection, इसलिए आपको अलग-अलग डेटाबेस कनेक्शन को अलग करने के तरीके के बारे में सोचने की आवश्यकता है।

मैंने IDbConnectionअलग-अलग डेटाबेस कनेक्शनों के अनुरूप कई इंटरफेस, 'इनहेरिट किए गए' , और SqlConnectionअलग-अलग डेटाबेस कनेक्शन स्ट्रिंग्स के साथ इंजेक्ट करने का प्रयास किया Startup

यह विफल रहा क्योंकि SqlConnectionविरासत में मिला है DbConnection, और DbConnectionकेवल कक्षा ही नहीं , IDbConnectionअपितु भी Component। तो आपके कस्टम इंटरफेस सिर्फ SqlConnectionनिहितार्थ का उपयोग करने में सक्षम नहीं होंगे ।

मैंने अपनी खुद की DbConnectionक्लास बनाने की भी कोशिश की जो अलग-अलग कनेक्शन स्ट्रिंग लेती है। यह बहुत जटिल है क्योंकि आपको DbConnectionकक्षा से सभी विधियों को लागू करना होगा । आप से मदद खो दिया है SqlConnection

मैं आखिर क्या कर रहा हूं

  1. दौरान Startup, मैंने सभी कनेक्शन स्ट्रिंग मानों को एक शब्दकोश में लोड किया। मैंने enumमैजिक स्ट्रिंग्स से बचने के लिए सभी डेटाबेस कनेक्शन नामों के लिए भी बनाया ।
  2. मैंने डिक्शनरी को सिंगलटन के रूप में इंजेक्ट किया।
  3. इंजेक्शन लगाने के बजाय IDbConnection, मैंने IDbConnectionFactoryसभी रिपॉजिटरी के लिए क्षणिक के रूप में बनाया और इंजेक्ट किया। अब सभी रिपॉजिटरी के IDbConnectionFactoryबजाय ले IDbConnection
  4. सही कनेक्शन कब चुनें? सभी रिपोजिटरी के निर्माण में! चीजों को साफ करने के लिए, मैंने रिपॉजिटरी बेस क्लास बनाए और बेस क्लास से रिपॉजिटरी विरासत में मिली। सही कनेक्शन स्ट्रिंग चयन बेस कक्षाओं में हो सकता है।

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 - मेरा अपना कारखाना कार्यान्वयन

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

फिर अन्य रिपॉजिटरी के लिए जिन्हें अन्य कनेक्शनों से बात करने की आवश्यकता है, आप उनके लिए एक अलग रिपॉजिटरी बेस क्लास बना सकते हैं।

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

        // ......
    }
}

आशा है कि ये सभी मदद करेंगे।


वास्तव में मैं क्या खोज रहा हूँ। मेरे पास एक ही समस्या थी और इसे उसी तरह से हल किया, मैं अभी भी नहीं जानता कि क्या यह एक अच्छा अभ्यास है लेकिन, मेरी राय में, मुझे लगता है कि यह है।
इवर्टन

1
क्या IServiceProvider गुंजाइश के लिए IDbConnection रजिस्टर करना बेहतर होगा? एक सेवा और अलग-अलग कनेक्शनों के साथ सिंगलटन स्कोप फैक्ट्री के रूप में पंजीकरण कर सकते हैं और var स्कोप = factory.CreateNonDefaultScope () का उपयोग कर सकते हैं; var कनेक्शन का उपयोग करना = गुंजाइश। सेवा। Piderider.GetRequiredService <IDbConnection> () आपको अपना गैर-डिफ़ॉल्ट कनेक्शन मिलेगा। कम विरासत साथ ही तानाना के साथ में मदद मिलेगी ...
बहुत

यही है जिसकी मेरे द्वारा तलाश की जा रही है। Awsome job @David धन्यवाद
शास्वत प्रकाश

27

मैंने एक संपत्ति के साथ विस्तार विधियां बनाईं जो कॉन्फ़िगरेशन से कनेक्शन स्ट्रिंग को पुनर्प्राप्त करता है। इससे कॉल करने वालों को कनेक्शन के बारे में कुछ भी पता नहीं चल पाता है, चाहे वह खुला हो या बंद, आदि। यह विधि आपको थोड़ी सी सीमित कर देती है क्योंकि आप कुछ Dapper कार्यक्षमता छिपा रहे हैं, लेकिन हमारे काफी सरल ऐप में यह हमारे लिए ठीक है। , और अगर हमें डैपर से अधिक कार्यक्षमता की आवश्यकता होती है, तो हम हमेशा एक नया एक्सटेंशन तरीका जोड़ सकते हैं जो इसे उजागर करता है।

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

1
एक सवाल यहां। चूंकि con.Query रिटर्न IEnumerable <T> है क्या यह कनेक्शन ऑब्जेक्ट के तुरंत निपटान के लिए सुरक्षित है? क्या तत्वों को पढ़ने के लिए IEnumerable को कनेक्शन की आवश्यकता नहीं है क्योंकि वे पढ़े जाते हैं? क्या हमें ToList () चलाना चाहिए?
एड्रियन नासुई

मुझे सत्यापित करने के लिए वापस डापर में जाना होगा, लेकिन मुझे पूरा यकीन है कि मैंने यह पैटर्न काम कर रहे उत्पादन कोड से लिया है। यह ठीक होना चाहिए - लेकिन निश्चित रूप से, आपको इंटरनेट पर किसी भी कोड का परीक्षण करना चाहिए।
शॉन हबर्ड

2
यदि आप एक डैपर क्वेरी एक्सटेंशन विधि का उपयोग कर रहे हैं, तो आपको कनेक्शन को स्पष्ट रूप से खोलने की आवश्यकता नहीं है क्योंकि यह विधि में ही किया गया है।
एच-राई १

4
उपरोक्त कोड के साथ समस्या यह है कि यदि आप बफ़र में पास होते हैं: क्वेरी विधि के लिए सही है, तो डेटा वापस आने से पहले कनेक्शन निपट जाएगा। आंतरिक रूप से, डैपर लौटने से पहले गणना करने योग्य सूची में बदल जाएगा।
ब्रायन वेलेलुंगा

@BrianVallelunga ऐसा नहीं होगा buffered: false?
जोडरेल

26

यह लगभग 4 साल पहले पूछा गया था ... लेकिन फिर भी, शायद जवाब यहां किसी के लिए उपयोगी होगा:

मैं सभी परियोजनाओं में इसे पसंद करता हूं। सबसे पहले, मैं एक बेस क्लास बनाता हूँ जिसमें कुछ सहायक विधियाँ होती हैं जैसे:

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

और इस तरह के आधार वर्ग होने से मैं आसानी से बिना किसी बॉयलरप्लेट कोड के असली रिपोजिटरी बना सकता हूं:

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

तो डैपर, SqlConnection-s और अन्य डेटाबेस एक्सेस सामान से संबंधित सभी कोड एक ही स्थान (BaseRepository) में स्थित है। सभी वास्तविक रिपोजिटरी स्वच्छ और सरल 1-लाइन विधियाँ हैं।

मुझे उम्मीद है कि यह किसी की मदद करेगा।


2
BaseRepositoryयह अनावश्यक विरासत है क्योंकि यह कोई सार्वजनिक या अमूर्त तरीके या गुण प्रदान नहीं करता है। इसके बजाय एक DBHelperवर्ग हो सकता है ।
जोश नू

हो सकता है कि CreateConnectionखुद की कक्षा में जाना बेहतर हो ?
हेलबॉय

हो सकता है ... लेकिन व्यक्तिगत रूप से मुझे सब कुछ सरल रखना पसंद है। यदि आपके पास CreateConnection (...) में बहुत सारे तर्क हैं, तो यह एक अच्छा विचार हो सकता है। मेरी परियोजनाओं में यह विधि "नया कनेक्शन लौटाओ (कनेक्शनस्ट्रीमिंग)" के समान सरल है, इसलिए इसे अलग से क्रोनकनेक्शन (...) विधि के बिना इनलाइन का उपयोग किया जा सकता है।
पावेल मेलनिकोव

1
इसके अलावा, जैसा कि निक-एस ने बताया, डैपर के नवीनतम संस्करणों में आपको डेटाबेस कनेक्शन को मैन्युअल रूप से खोलने की आवश्यकता नहीं है। डैपर इसे आपके लिए अपने आप खोल देगा। पोस्ट को अपडेट किया।
पावेल मेलनिकोव

इसे इमो इंजेक्ट करें। services.AddScoped<IDbConnection>(p => new SqlConnection(connString)इसके बाद सिर्फ इसके लिए पूछें जहां जरूरत है
सिनास्टेटिक

8

मैं इसे इस तरह से करता हूं:

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

फिर, जहां भी मैं अपनी निर्भरता तार-तार करता हूं (उदा: Global.asax.cs या Startup.cs), मैं कुछ इस तरह करता हूं:

var connectionFactory = new Func<IDbConnection>(() => {
    var conn = new SqlConnection(
        ConfigurationManager.ConnectionStrings["connectionString-name"];
    conn.Open();
    return conn;
});

एक सवाल यहां। चूंकि con.Query रिटर्न Ienumerable है <T> क्या यह कनेक्शन के तुरंत निपटान के लिए सुरक्षित है? क्या तत्वों को पढ़ने के लिए IEnumerable को कनेक्शन की आवश्यकता नहीं है क्योंकि वे पढ़े जाते हैं?
एड्रियन नसुई

1
@ AdrianNasui: वर्तमान में, डैपर का डिफ़ॉल्ट व्यवहार आपके एसक्यूएल को निष्पादित करने और रिटर्न पर पूरे रीडर को बफर करने के लिए IEnumerable<T>है , इसलिए यह पहले से ही भौतिक है। यदि आप पास करते हैं buffered: false, तो हाँ, आपको usingब्लॉक से बाहर निकलने से पहले आउटपुट का उपभोग करना होगा ।
जैकब क्राल

7

सर्वोत्तम अभ्यास एक वास्तविक भरा हुआ शब्द है। मुझे डैपर की तरह एक DbDataContextस्टाइल कंटेनर पसंद है । यह आपको लेन-देन, लेनदेन और अन्य सहायकों की जोड़ी बनाने की अनुमति देता है । CommandTimeout

उदाहरण के लिए:

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

15
क्या OP SqlConnection ([[CONN STRING HERE]]) भाग के बारे में अधिक नहीं पूछ रहा है? वह कहते हैं, "लेकिन मुझे हर वर्ग में (यहां तक ​​कि प्रत्येक विधि में) एक कनेक्शन स्ट्रिंग का संदर्भ देना गलत लगता है" मुझे लगता है कि वह सोच रहा है कि क्या हमें Dapper उपयोगकर्ताओं ने कनेक्शन-निर्माण पक्ष को लपेटने के लिए चारों ओर एक पैटर्न (प्रकार का) उत्पन्न किया है DRY / उस तर्क को छिपाओ। (एक तरफ ओपी के लिए, अगर आप Dapper.Rainbow का उपयोग कर सकते हैं, तो ऐसा करें ... यह वास्तव में अच्छा है!)
ckittel

4

इसे इस्तेमाल करे:

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

    }

6
आप अपने समाधान में कनेक्शन को कैसे बंद / निपटारा करते हैं?
jpshook

@ जेपीएसहुक - मेरा मानना ​​है कि वह प्रयोग कर रहा है। (ref stackoverflow.com/a/4717859/2133703 )
मैकगिवेर

4

हर कोई अपने कनेक्शन पूरी तरह से बहुत जल्दी खोल रहा है? मेरे पास यही सवाल था, और यहाँ स्रोत के माध्यम से खुदाई करने के बाद - https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper/SqlMapper.cs

आप पाएंगे कि डेटाबेस के साथ प्रत्येक इंटरैक्शन यह देखने के लिए कनेक्शन की जांच करता है कि क्या यह बंद है, और आवश्यकतानुसार इसे खोलता है। इसके कारण, हम केवल ऊपर दिए गए कथनों को बिना कंवर्जन () के उपयोग करते हैं। इस तरह से कनेक्शन संभव के रूप में बातचीत के करीब के रूप में खोला जाता है। यदि आप नोटिस करते हैं, तो यह तुरंत कनेक्शन बंद कर देता है। यह निपटान के दौरान स्वचालित रूप से बंद होने से भी तेज होगा।

उपरोक्त रेपो से इसके कई उदाहरणों में से एक:

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

नीचे एक छोटा सा उदाहरण है कि कैसे हम डैपर के लिए रैपर का उपयोग करते हैं जिसे डैपरव्रेपर कहा जाता है। यह हमें कनेक्शन प्रबंधित करने, सुरक्षा प्रदान करने, लॉग इन करने आदि के लिए सभी डैपर और सरल क्रूड विधियों को लपेटने की अनुमति देता है।

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

1
यह वास्तव में उपयोगी है कि यह जानते हुए कि डैपर कनेक्शन खुला छोड़ देगा अगर यह पहले से ही खुला हो जाता है। अब मैं dber के साथ इसे पास / उपयोग करने से पहले db कनेक्शन को प्री-ओपन कर रहा हूँ और मुझे एक 6x प्रदर्शन लाभ मिला है - धन्यवाद!
क्रिस स्मिथ

2

मैं सहायक वर्ग के साथ संबंध लपेटता हूं:

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
}

उपयोग के उदाहरण:

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

इसलिए मुझे हर बार कनेक्शन को स्पष्ट रूप से नहीं खोलना पड़ता। इसके अतिरिक्त, आप इसे इस तरह से उपयोग कर सकते हैं कि भविष्य के रिफैक्टरिंग की सुविधा के लिए:

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

इस उत्तरTableName<T>() में क्या पाया जा सकता है ।


0

हाय @donaldhughes मैं इस पर भी नया हूँ, और मैं यह करने के लिए उपयोग करता हूं: 1 - मेरे कनेक्शन को प्राप्त करने के लिए एक वर्ग बनाएं 2 स्ट्रिंग - कनेक्शन का उपयोग करके स्ट्रिंग वर्ग को कॉल करें

देखो:

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

और यह ठीक काम करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.