Общий шаблон репозитория для ядра .net с Dapper - PullRequest
0 голосов
/ 20 сентября 2018

Я следовал руководству по шаблону универсального репозитория с ядром ASP.NET с EF CORE, здесь , например

   public class Repository<T> : IRepository<T> where T : class
   {
    protected readonly DbContext _dbContext;
    protected readonly DbSet<T> _dbSet;

    public Repository(DbContext context)
    {
        _dbContext = context ?? throw new 
         ArgumentException(nameof(context));
        _dbSet = _dbContext.Set<T>();
    }

    public void Add(T entity)
    {
       _dbSet.Add(entity);
    }
   }

, так как это использует EF Core, мы можем просто использовать его предварительноопределенные методы для вставки данных с помощью метода Add, но когда дело доходит до dapper, требуется запрос sql, тогда как я могу создать этот универсальный интерфейс, подходящий для Dapper?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Примеры по запросу @PathumLakshan из комментариев.Приведенные примеры написаны асинхронно, но источник может быть реализован синхронно.В любом случае, это просто иллюстрация того, как вы можете управлять инфраструктурой с помощью Dapper.Класс Db предоставляет некоторые общие методы для получения данных и выполнения запросов SQL.Например, вы можете использовать перегрузку Get<T>(string, object) для базовых запросов или взять Get<T>(Func<SqlConnection, SqlTransaction, int, Task<T>>, чтобы использовать, скажем, QueryMultiple.Класс Repository<Entity> показывает, как может выглядеть базовый репозиторий для сущности Entity.

Db Класс:

public class Db : IDb
{
    private readonly Func<SqlConnection> _dbConnectionFactory;

    public Db(Func<SqlConnection> dbConnectionFactory)
    {
        _dbConnectionFactory = dbConnectionFactory ?? throw new ArgumentNullException(nameof(dbConnectionFactory));
    }

    public async Task<T> CommandAsync<T>(Func<SqlConnection, SqlTransaction, int, Task<T>> command)
    {
        using (var connection = _dbConnectionFactory.Invoke())
        {
            await connection.OpenAsync();

            using (var transaction = connection.BeginTransaction())
            {
                try
                {
                    var result = await command(connection, transaction, Constants.CommandTimeout);

                    transaction.Commit();

                    return result;
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    Logger.Instance.Error(ex);
                    throw;
                }
            }
        }
    }

    public async Task<T> GetAsync<T>(Func<SqlConnection, SqlTransaction, int, Task<T>> command)
    {
        return await CommandAsync(command);
    }

    public async Task<IList<T>> SelectAsync<T>(Func<SqlConnection, SqlTransaction, int, Task<IList<T>>> command)
    {
        return await CommandAsync(command);
    }

    public async Task ExecuteAsync(string sql, object parameters)
    {
        await CommandAsync(async (conn, trn, timeout) =>
        {
            await conn.ExecuteAsync(sql, parameters, trn, timeout);
                return 1;
        });

    public async Task<T> GetAsync<T>(string sql, object parameters)
    {
        return await CommandAsync(async (conn, trn, timeout) =>
        {
            T result = await conn.QuerySingleAsync<T>(sql, parameters, trn, timeout);
            return result;
        });
    }

    public async Task<IList<T>> SelectAsync<T>(string sql, object parameters)
    {
        return await CommandAsync<IList<T>>(async (conn, trn, timeout) =>
        {
            var result = (await conn.QueryAsync<T>(sql, parameters, trn, timeout)).ToList();
            return result;
        });
    }
}

Репозиторий Класс:

public class Repository<Entity> : IRepository<Entity>
{
    protected readonly IDb _db;

    public Repository(IDb db)
    {
        _db = db ?? throw new
            ArgumentException(nameof(db));
    }

    public async Task Add(Entity entity)
    {
        await _db.ExecuteAsync("INSERT INTO ... VALUES...", entity);
    }

    public async Task Update(Entity entity)
    {
        await _db.ExecuteAsync("UPDATE ... SET ...", entity);
    }

    public async Task Remove(Entity entity)
    {
        await _db.ExecuteAsync("DELETE FROM ... WHERE ...", entity);
    }

    public async Task<Entity> FindByID(int id)
    {
        return await _db.GetAsync<Entity>("SELECT ... FROM ... WHERE Id = @id", new { id });
    }

    public async Task<IEnumerable<Entity>> FindAll()
    {
        return await _db.SelectAsync<Entity>("SELECT ... FROM ... ", new { });
    }
}

Db можно расширить с помощью другого универсального метода, например, ExecuteScalar, который понадобится вам в ваших репозиториях.Надеюсь, это поможет.

0 голосов
/ 20 сентября 2018

У нас был проект, в котором у нас был универсальный репозиторий dapper, но после того, как проект эволюционировал, у нас есть ditched универсальный репозиторий, чтобы использовать реальную силу dapper.

Я бы порекомендовалиспользуйте Dapper как прямой без общих операций CRUD.

Чтобы продемонстрировать, что у нас было, я предоставлю пример кода, который не готов к производству, даст вам идею реализовать ваше собственное универсальное репо.

public abstract class ConnectionBase : IDbConnection
{

    protected ConnectionBase(IDbConnection connection)
    {
        Connection = connection;
    }

    protected IDbConnection Connection { get; private set; }

    // Verbose but necessary implementation of IDbConnection:
    #region "IDbConnection implementation"

    public string ConnectionString
    {
        get
        {
            return Connection.ConnectionString;
        }

        set
        {
            Connection.ConnectionString = value;
        }
    }

    public int ConnectionTimeout
    {
        get
        {
            return Connection.ConnectionTimeout;
        }
    }

    public string Database
    {
        get
        {
            return Connection.Database;
        }
    }

    public ConnectionState State
    {
        get
        {
            return Connection.State;
        }
    }

    public IDbTransaction BeginTransaction()
    {
        return Connection.BeginTransaction();
    }



    public void Close()
    {
        Connection.Close();
    }

    public IDbCommand CreateCommand()
    {
        return Connection.CreateCommand();
    }

    public void Dispose()
    {
        Connection.Dispose();
    }

    public void Open()
    {
        Connection.Open();
    }

    #endregion
}

Универсальный репозиторий

public abstract class GenericRepository<T> : IRepository<T> where T : class //EntityBase, IAggregateRoot
    {

        private readonly string _tableName;


        internal IDbConnection Connection
        {
            get
            {
                return new SqlConnection(ConfigurationManager.ConnectionStrings["SmsQuizConnection"].ConnectionString);
            }
        }

        public GenericRepository(string tableName)
        {
            _tableName = tableName;
        }

        internal virtual dynamic Mapping(T item)
        {
            return item;
        }

        public virtual void Add(T item)
        {
            using (IDbConnection cn = Connection)
            {
                var parameters = (object)Mapping(item);
                cn.Open();
                item.ID = cn.Insert<Guid>(_tableName, parameters);
            }
        }

        public virtual void Update(T item)
        {
            using (IDbConnection cn = Connection)
            {
                var parameters = (object)Mapping(item);
                cn.Open();
                cn.Update(_tableName, parameters);
            }
        }

        public virtual void Remove(T item)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                cn.Execute("DELETE FROM " + _tableName + " WHERE ID=@ID", new { ID = item.ID });
            }
        }

        public virtual T FindByID(Guid id)
        {
            T item = default(T);

            using (IDbConnection cn = Connection)
            {
                cn.Open();
                item = cn.Query<T>("SELECT * FROM " + _tableName + " WHERE ID=@ID", new { ID = id }).SingleOrDefault();
            }

            return item;
        }



        public virtual IEnumerable<T> FindAll()
        {
            IEnumerable<T> items = null;

            using (IDbConnection cn = Connection)
            {
                cn.Open();
                items = cn.Query<T>("SELECT * FROM " + _tableName);
            }

            return items;
        }



    }
...