using Dapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Kean.Infrastructure.Database
{
///
/// 基于 Dapper 的 SQL Server 数据库对象的操作
///
/// 数据库对象映射的实体类型
internal sealed class MssqlDapperSchema : ISchema
where T : IEntity
{
private readonly IDbContext _context; // 上下文
private readonly string _schema; // 对象
private IEnumerable<(string property, string name, string alias, IdentifierAttribute identifier, ComputedAttribute computed)> _columns; //字段
private string _where; // 条件语句
private string _order; // 排序语句
private string _group; // 分组语句
private string _having; // 分组条件语句
private string _lock; // 锁类型
private int _skip; // 跳过数
private int _take; // 结果数
private bool _distinct; // 去重标记
private Parameters _param; // 参数(查询)
private Parameters _value; // 值(更新)
internal MssqlDapperSchema(IDbContext context, string name = null)
{
_context = context;
_schema = $"[{name ?? typeof(T).Name.Split('`')[0]}]";
Initialize();
}
internal void Initialize()
{
_columns = typeof(T).GetProperties().Select(p =>
(
p.Name,
$"[{p.Name}]",
$"[{p.Name}]",
p.GetCustomAttribute(),
p.GetCustomAttribute()
));
_where = null;
_order = null;
_group = null;
_having = null;
_lock = null;
_skip = 0;
_take = 0;
_distinct = false;
_param = null;
_value = null;
}
private string BuildInsert()
{
return string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
_schema,
string.Join(',', _columns.Where(c => c.identifier?.Increment != true && c.computed == null).Select(c => c.name)),
string.Join(',', _columns.Where(c => c.identifier?.Increment != true && c.computed == null).Select(c => $"@{c.property}"))
);
}
private string BuildUpdate()
{
var i = 0;
return string.Format("UPDATE {0} SET {1} WHERE {2}",
_schema,
string.Join(',', _value.ParameterNames.Select(v => $"[{v}]=@v{i++}")),
_where
);
}
private string BuildDelete()
{
return string.Format("DELETE FROM {0}{1}",
_schema,
_where == null ? string.Empty : $" WHERE {_where}"
);
;
}
private string BuildSelect()
{
var buffer = new StringBuilder("SELECT");
if (_skip == 0)
{
if (_take > 0)
{
buffer.Append($" TOP {_take}");
}
}
if (_distinct)
{
buffer.Append(" DISTINCT");
}
buffer.Append($" {string.Join(',', _columns.Select(c => c.name == c.alias ? c.name : $"{c.name} AS {c.alias}"))}");
if (_skip > 0)
{
buffer.Append($",ROW_NUMBER() OVER (ORDER BY {_order ?? _columns.First().name}) AS [ROW_NUM]");
}
buffer.Append($" FROM {_schema}");
if (_lock != null)
{
buffer.Append($" WITH({_lock})");
}
if (_where != null)
{
buffer.Append($" WHERE {_where}");
}
if (_group != null)
{
buffer.Append($" GROUP BY {_group}");
}
if (_having != null)
{
buffer.Append($" HAVING {_having}");
}
if (_skip == 0)
{
if (_order != null)
{
buffer.Append($" ORDER BY {_order}");
}
return buffer.ToString();
}
else
{
return string.Format("SELECT{0} {1} FROM ({2}) AS T WHERE [ROW_NUM] > {3} ORDER BY [ROW_NUM]",
_take == 0 ? string.Empty : $" TOP {_take}",
string.Join(',', _columns.Select(c => c.alias)),
buffer,
_skip);
}
}
public Query Query(Expression> expression)
{
var mapping = MappingExpression.Build(expression, null, "[]");
_columns = mapping.Select(i =>
(
default(string),
i.Item1,
i.Item2,
default(IdentifierAttribute),
default(ComputedAttribute)
));
var query = new Query
{
Expression = BuildSelect(),
Parameters = _param
};
Initialize();
return query;
}
public async Task