Preliminary --2.ORM Asp.net Core Series: Dapper achieve MySql databases of various types of operation

ChuanGoing 2019-09-10

  A distance of nearly a month on and off only then Benpian the code finished, later accelerate progress towards the year to complete a basic introduction to this series, and I urge continuous learning.

Benpian learning curve:

1. acquaintance Dapper

2.DbConnection

3.CommandBuilder single-table operation (omitted)

4. demonstration

 

Dapper acquaintance

  Dapper is a lightweight / performance ORM, core functions using data acquired Emit reflected in IDataReader. We can make use of its object-relational mapping simple CURD operations, or implement complex scenes directly with the SQL statement CURD operations.

DbConnection

  As the name suggests, the database connection object. Dapper DbConnection provide extended to operate the database objects

public virtual int Execute(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return _dbConnection.Execute(sql: sql, param: param, transaction: null, commandTimeout: commandTimeout, commandType: commandType);
        }

        public virtual IEnumerable<TResult> Query<TResult>(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return _dbConnection.Query<TResult>(sql: sql, param: param, transaction: null, commandTimeout: commandTimeout, commandType: commandType);
        }
View Code

  Posted above two methods: Execute method performed (additions and deletions), Query operation to execute the query. It can be seen, Dapper database operations are mainly hand-written SQL, of course, we can also package some common ways to improve development efficiency.

  Of course herein, this focus is not introduced Dapper's. Then take a look at how to package an ORM Dapper ourselves available.

CommandBuilder single-table operations need to achieve universal single-table additions and deletions to change search, we have to define / decomposition SQL statement:

1. The operation of the object table (Table)

2. Column object table object (field)

3. Conditions

Defined field object / object set

public class Field
    {
        public Field(string name, object value = null)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name), "invalid name");
            }
            Name = name;
            Value = value;
        }
        public string Name { set; get; }
        public object Value { set; get; }
    }
View Code
 public class FieldsCollection : IEnumerable<Field>
    {
        private List<Field> _fields;
        public Field this[int index] => _fields[index];

        public FieldsCollection()
        {
            _fields = new List<Field>();
        }
        
        public int Count => _fields.Count;

        public void Add(Field field)
        {
            _fields.Add(field);
        }

        public void Add(params Field[] fields)
        {
            _fields.AddRange(fields);
        }

        public IEnumerable<Field> GetFields()
        {
            return _fields;
        }

        public IEnumerator<Field> GetEnumerator()
        {
            return _fields.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _fields.GetEnumerator();
        }
    }
View Code

Defined conditions

public abstract class Filter
    {
        public Filter(string field)
        {
            Field = field;
        }
        public virtual string Field { get; private set; }
    }
View Code
 /// <summary>
    /// 相等过滤
    /// </summary>
    public class EqualFilter : Filter
    {
        public EqualFilter(string field, object value)
            : base(field)
        {
            Value = value;
        }
        public object Value { get; }
    }
View Code

Posted here only "equal" conditions, please see the detailed code Github source link given in the end of chapter

Define the sort field

 public class Sort
    {
        public Sort(string column, bool asc = true)
        {
            ColumnName = column;
            ASC = asc;
        }
        public string ColumnName { get; set; }
        public bool ASC { get; set; }
    }
View Code

Assembly of the query

public class QueryParameter
    {
        private List<Filter> _filters;
        private List<Sort> _sorts;
        public QueryParameter(FieldsCollection fileds, IEnumerable<Filter> filters = null, IEnumerable<Sort> sorts = null)
        {
            Fields = fileds.GetFields();
            _filters = new List<Filter>();
            if (filters != null)
            {
                _filters.AddRange(filters);
            }
            _sorts = new List<Sort>();
            if (sorts != null)
            {
                _sorts.AddRange(sorts);
            }
        }

        public void AddFilter(Filter filter)
        {
            _filters.Add(filter);
        }

        public void AddSort(Sort sort)
        {
            _sorts.Add(sort);
        }

        public IEnumerable<Field> Fields { get; }
        public IEnumerable<Filter> Filters => _filters;
        public IEnumerable<Sort> Sorts => _sorts;
    }
View Code

After completing the above object definition, let us look at how to use the target to complete CRUD operations

 public SqlCommand GetCommand(TPrimaryKey key)
        {
            var obj = GetObjectContext<TEntity>();
            FieldsCollection fields = new FieldsCollection();
            List<Filter> filters = new List<Filter>();
            foreach (var prop in obj.Properties)
            {
                foreach (var attr in prop.Attributes)
                {
                    if (attr is PrimaryKeyAttribute keyAttr)
                    {
                        filters.Add(new Equal(prop.Info.Name, key));
                    }
                }

                fields.Add(new Field(prop.Info.Name));
            }

            QueryParameter queryParameter = new QueryParameter(fields, filters);
            return CommandBuilder.QueryCommand(obj.Table, queryParameter, count: 1);
        }

 

Query is made based on the main key query, the database in which the context object obtained by the object reflector generic

  public virtual ObjectContext GetObjectContext<T>()
        {
            var type = typeof(T);

            string tableKey = ObjectContext.GetTableKey(typeof(T));

            return DbContext.ObjectCollection.GetOrAdd(tableKey, entity => new ObjectContext(type));
        }

 

New method similar to the above query, but there are differences in the form of SQL statements

public SqlCommand InsertCommand(TEntity entity)
        {
            var obj = GetObjectContext<TEntity>();
            FieldsCollection fields = new FieldsCollection();
            foreach (var prop in obj.Properties)
            {
                fields.Add(new Field(prop.Info.Name, prop.Info.GetValue(entity)));
            }
            var com = CommandBuilder.InsertCommand(obj.Table, fields);
            return com;
        }

 

Query / add method can be seen that the above code parameters obtained by reflecting the CRUD / cache / worth of information, so far there has not form a valid SQL statement. So how do you achieve it?

Because each database (Mysql / Mssql / oracle ..) are some differences in the SQL syntax, so the work should be completed by converting SQL specific statement of some sort of database generator to generate. This example uses Mysql database, so we can see the appeal of code involved CommandBuilder is based on the specific code implemented in mysql not posted here for details see endnote Github link.

 Show

Based on an Asp.net Core series of event-driven --1 Study: Simple event bus for (SimpleEventBus) , redrafting CustomersController, repository operations by the direct replacement for the package code by sql statement Benpian achieved, then the event / defined event processing entity / Dto Domain layer moves like (for subsequent description paving)

private readonly IRepository<Customer, Guid> _repository;
        private readonly IEventBus _eventBus;

        public CustomersController(IEventBus eventBus, IRepository<Customer, Guid> repository)
        {
            _repository = repository;
            _eventBus = eventBus;
        }


        // 获取指定ID的客户信息
        [HttpGet("{id}")]
        public async Task<IActionResult> Get(Guid id)
        {
            var customer = await _repository.GetAsync(id);

            if (customer == null)
            {
                return NotFound();
            }
            return Ok(customer);
        }

        // 创建新的客户信息
        [HttpPost]
        public async Task<IActionResult> Create([FromBody] CustomerDto model)
        {
            var name = model.Name;
            if (string.IsNullOrEmpty(name))
            {
                return BadRequest();
            }

            var customer = new Customer(name);
            var result = await _repository.InsertAsync(customer);
            await _eventBus.PublishAsync(new CustomerCreatedEvent(name));

            return Created(Url.Action("Get", new { id = customer.Id }), customer.Id);
        }

After running the program, get the correct data is returned

 

 

 

ORM Dapper achieve the basic functions of this calculation come to an end, readers are interested can access Dapper source, follow-up there is a chance it will introduce extensions under

 

review

  Recall In this part, first of all referred simply describes what Dapper is, what to do, and then we realized the mysql-based Simple Object-relational mapping of Dapper. Finally, Invoke-WebRequest simulation http WinPowershell request demonstrates the creation of data to get.

  Benpian have been related to the concept of warehousing, is also an important part of the domain model, we will follow the progressive introduction DDD concepts and design principles

Code

  Benpian Github source involved in the https://github.com/ChuanGoing/Start.git  can find DapperOrm branches.

 

Guess you like

Origin www.cnblogs.com/ChuanGoing/p/11401321.html