.NET'te Dapper ile Veritabanı Bağlantılarını nasıl idare ederim?


86

Dapper ile oynuyordum, ancak veritabanı bağlantısını halletmenin en iyi yolundan emin değilim.

Çoğu örnek, örnek sınıfta veya hatta her yöntemde oluşturulan bağlantı nesnesini gösterir. Ancak, web.config'den çekilse bile, her clss'de bir bağlantı dizesine başvurmak bana yanlış geliyor.

Deneyimlerim a DbDataContextveya DbContextLinq to SQL veya Entity Framework kullanımıyla oldu, bu yüzden bu benim için yeni.

Veri Erişim stratejim olarak Dapper'ı kullanırken web uygulamalarımı nasıl yapılandırırım?


Çok geç ama; Bunu şu şekilde uyguladım: stackoverflow.com/a/45029588/5779732
Amit Joshi

using-dapper-asynchronously-in-asp-net-core-2 - exceptionnotfound.net/…
Himalaya Garg

Yanıtlar:


54

Microsoft.AspNetCore.All : v2.0.3 | Zarif : v1.50.2

En iyi uygulamaları doğru kullanıp kullanmadığımdan emin değilim, ancak birden çok bağlantı dizesini işlemek için bunu bu şekilde yapıyorum .

Yalnızca 1 bağlantı dizeniz varsa kolaydır

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'den fazla bağlantı dizeniz varsa sorunlar

Kullanıldığı Dapperiçin IDbConnection, farklı veritabanı bağlantılarını ayırt etmenin bir yolunu düşünmeniz gerekir.

IDbConnectionFarklı veritabanı bağlantılarına karşılık gelen , 'miras alınan' birden çok arabirim oluşturmaya ve SqlConnectionfarklı veritabanı bağlantı dizeleriyle enjekte etmeye çalıştım Startup.

Bu başarısız oldu çünkü sadece sınıftan değil , aynı zamanda sınıftan SqlConnectionmiras alır DbConnectionve DbConnectiononu ekler . Böylece, özel arayüzleriniz sadece uygulamayı kullanamayacak.IDbConnectionComponentSqlConnection

Ayrıca DbConnectionfarklı bağlantı dizesi alan kendi sınıfımı oluşturmaya çalıştım . Bu çok karmaşık çünkü tüm yöntemleri DbConnectionsınıftan uygulamanız gerekiyor. Yardımını kaybettin SqlConnection.

Ne yapıyorum

  1. Bu sırada Startuptüm bağlantı dizesi değerlerini bir sözlüğe yükledim. Ayrıca enumsihirli dizelerden kaçınmak için tüm veritabanı bağlantı adları için bir de oluşturdum .
  2. Sözlüğü Singleton olarak enjekte ettim.
  3. Enjekte etmek yerine IDbConnection, bunu IDbConnectionFactorytüm depolar için Geçici olarak yarattım ve enjekte ettim. Artık tüm depolar IDbConnectionFactoryyerine alıyor IDbConnection.
  4. Doğru bağlantıyı ne zaman seçmelisiniz? Tüm depoların kurucusunda! İşleri temizlemek için, depo temel sınıfları oluşturdum ve depoların temel sınıflardan miras almasını sağladım. Doğru bağlantı dizesi seçimi temel sınıflarda gerçekleşebilir.

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 - kendi fabrika uygulamam

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

Daha sonra, diğer bağlantılarla konuşması gereken diğer havuzlar için, onlar için farklı bir depo temel sınıfı oluşturabilirsiniz.

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

        // ......
    }
}

Umarım tüm bunlar yardımcı olur.


Tam olarak aradığım şey. Ben de aynı sorunu yaşadım ve aynı şekilde çözdüm, bunun iyi bir uygulama olup olmadığını hala bilmiyorum ama bence öyle.
Ewerton

1
IServiceProvider kapsamı için IDbConnection'ı kaydetmek daha iyi olur mu? Hizmet oluşturabilir ve farklı bağlantılarla ve var kapsam = factory.CreateNonDefaultScope (); var connection = kapsam.ServiceProvider.GetRequiredService <IDbConnection> () kullanarak varsayılan olmayan bağlantınızı alırsınız. Az miras ... sıra genişletilebilirlik yardımcı olacaktır
çok

Aradığım şey bu. Harika bir iş @ David. Teşekkürler
Shashwat Prakash

27

Konfigürasyondan bağlantı dizesini alan bir özelliğe sahip uzantı yöntemleri oluşturdum. Bu, arayanların bağlantı hakkında herhangi bir şey bilmek zorunda kalmamalarını sağlar, ister açık ister kapalı olsun, vb. Bu yöntem, bazı Dapper işlevlerini gizlediğiniz için sizi biraz sınırlar, ancak oldukça basit uygulamamızda bizim için iyi çalıştı. ve Dapper'dan daha fazla işlevselliğe ihtiyaç duyarsak, her zaman onu ortaya çıkaran yeni bir uzantı yöntemi ekleyebilirdik.

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
Burada bir soru var. Conn.Query, IEnumerable <T> döndürdüğünden, bağlantı nesnesini hemen atmak güvenli midir? Öğeleri okundukları gibi gerçekleştirmek için IEnumerable'ın bağlantıya ihtiyacı yok mu? ToList () çalıştırmalı mıyız?
Adrian Nasui

Doğrulamak için Dapper'a geri dönmem gerekecek, ancak bu kalıbı çalışan üretim kodundan olduğu gibi aldığımdan oldukça eminim. Sorun değil - ama tabii ki internette herhangi bir kodu test etmelisiniz.
Shawn Hubbard

2
Şık bir Query uzantısı yöntemi kullanıyorsanız, yöntemin kendisinde yapıldığı için bağlantıyı açıkça açmanız gerekmez.
h-rai

4
Yukarıdaki kodla ilgili sorun, arabelleğe alınmış: true Sorgu yöntemine geçerseniz, veri döndürülmeden önce bağlantının ortadan kalkmasıdır. Dahili olarak, Dapper, dönmeden önce numaralandırılabilir olanı bir listeye dönüştürecektir.
Brian Vallelunga

@BrianVallelunga değil buffered: falsemi?
Jodrell

26

Yaklaşık 4 yıl önce sorulmuştu ... ama her neyse, belki cevap buradaki biri için faydalı olacaktır:

Tüm projelerde böyle yapıyorum. İlk olarak, bunun gibi birkaç yardımcı yöntem içeren bir temel sınıf oluşturuyorum:

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

Ve böyle bir temel sınıfa sahip olarak, herhangi bir ortak kod olmadan kolayca gerçek depolar oluşturabilirim:

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

Dapper, SqlConnection-s ve diğer veritabanı erişim öğeleri ile ilgili tüm kodlar tek bir yerde (BaseRepository) bulunur. Tüm gerçek depolar temiz ve basit 1 satırlık yöntemlerdir.

Umarım birine yardımcı olur.


2
BaseRepositoryherhangi bir genel veya soyut yöntem veya özellik sağlamadığı için gereksiz kalıtımdır. Bu, bunun yerine bir DBHelpersınıf olabilir.
Josh Noe

CreateConnectionKendi sınıfına geçmek daha iyi olabilir mi?
hellboy

Olabilir ... Ama şahsen her şeyi basit tutmayı seviyorum. CreateConnection'da (...) çok fazla mantığınız varsa, bu iyi bir fikir olabilir. Projelerimde bu yöntem "yeni Bağlantı döndür (connectionString)" kadar basittir, bu nedenle ayrı CreateConnection (...) yöntemi olmadan satır içi kullanılabilir.
Pavel Melnikov

1
Ayrıca nicklerin de belirttiği gibi, Dapper'ın en son sürümlerinde veritabanı bağlantısını manuel olarak açmanıza gerek yoktur. Dapper sizin için otomatik olarak açacaktır. gönderiyi güncelledi.
Pavel Melnikov

enjekte imo. services.AddScoped<IDbConnection>(p => new SqlConnection(connString)o zaman gerektiği yerde isteyin
Sinaesthetic

8

Bunu böyle yapıyorum:

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

Ardından, bağımlılıklarımı bağladığım her yerde (ör. Global.asax.cs veya Startup.cs), şöyle bir şey yapıyorum:

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

Burada bir soru var. Conn.Query, Ienumerable <T> döndürdüğünden, bağlantıyı hemen kesmek güvenli midir? Öğeleri okundukları gibi gerçekleştirmek için IEnumerable'ın bağlantıya ihtiyacı yok mu?
Adrian Nasui

1
@AdrianNasui: Şu anda, Dapper'in varsayılan davranışı, SQL'inizi yürütmek ve geri dönüşte tüm okuyucuyu tamponlamaktır, böylece IEnumerable<T>zaten gerçekleştirilmiştir. Geçerseniz buffered: false, evet, usingbloktan çıkmadan önce çıkışı tüketmeniz gerekecektir .
Jacob Krall

7

En iyi uygulama, gerçekten yüklü bir terimdir. Ben gibi DbDataContextgibi stil konteyner Dapper.Rainbow teşvik etmektedir. CommandTimeoutİşlemi ve diğer yardımcıları birleştirmenize olanak tanır .

Örneğin:

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]]) kısmı hakkında daha fazla soru sormuyor mu? "Ama her sınıfta (her yöntemde bile) bir bağlantı dizesine başvurmak bana yanlış geliyor" diyor. Sanırım biz Dapper kullanıcılarının, şeylerin bağlantı oluşturma tarafını sararak bir model (türden) oluşturup oluşturmadığını merak ediyor. KURU / bu mantığı sakla. (OP'nin yanı sıra, Dapper.Rainbow'u kullanabilirseniz, öyle yapın ... gerçekten güzel!)
ckittel

4

Bunu dene:

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
Çözümünüzde bağlantının kapatılması / elden çıkarılması ile nasıl başa çıkıyorsunuz?
jpshook

@JPShook - Kullandığına inanıyorum. (ref stackoverflow.com/a/4717859/2133703 )
MacGyver

4

Görünüşe göre herkes bağlantılarını çok erken mi açıyor? Aynı soruyu da sormuştum ve buradaki Kaynağı araştırdıktan sonra - https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper/SqlMapper.cs

Veritabanıyla yapılan her etkileşimin bağlantıyı kontrol edip kapatılıp kapatılmadığını göreceksiniz ve gerektiğinde açacaksınız. Bundan dolayı, yukarıdaki gibi ifadeleri conn.open () kullanmadan kullanıyoruz. Bu şekilde bağlantı, etkileşime mümkün olduğu kadar yakın açılır. Fark ederseniz, bağlantıyı da hemen kapatır. Bu ayrıca, atma sırasında otomatik olarak kapanmasından daha hızlı olacaktır.

Yukarıdaki depodan bunun birçok örneğinden biri:

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

Aşağıda, Dapper için DapperWrapper adlı bir Wrapper'ı nasıl kullandığımıza dair küçük bir örnek verilmiştir. Bu, bağlantıları yönetmek, güvenlik sağlamak, günlük kaydı vb. İçin tüm Dapper ve Simple Crud yöntemlerini sarmamıza olanak tanır.

  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
Bu, Dapper'ın bağlantıyı aldığında zaten açıksa, bağlantıyı açık bırakacağını bilmek gerçekten yararlıdır. Şimdi Dapper ile geçmeden / kullanmadan önce db bağlantısını önceden açıyorum ve 6 kat performans kazancım var - teşekkürler!
Chris Smith

2

Yardımcı sınıfla bağlantıyı kuruyorum:

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
}

Kullanım örnekleri:

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

Bu yüzden her seferinde bağlantıyı açıkça açmam gerekmiyor. Ek olarak, gelecekteki yeniden düzenlemenin rahatlığı için şu şekilde kullanabilirsiniz:

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

Bu cevapta ne TableName<T>()bulunabilir .


0

Merhaba @donaldhughes Ben de bu konuda yeniyim ve bunu yapmak için kullanıyorum: 1 - Bağlantı Dizimi almak için bir sınıf oluşturun 2 - Kullanarak bağlantı dizesi sınıfını arayın

Bak:

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

Ve iyi çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.