一、实体查询

using MyOrm.Commons;
using MyOrm.DbParameters;
using MyOrm.Expressions;
using MyOrm.Mappers;
using MyOrm.Reflections;
using MyOrm.SqlBuilder;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text; namespace MyOrm.Queryable
{
public class MyQueryable<T> where T : class , new ()
{
private readonly string _connectionString; // 要查询的导航属性
private readonly Dictionary<string, string[]> _includeProperties = new Dictionary<string, string[]>(); // Where子句中包含导航属性
private List<string> _whereProperties = new List<string>(); // 导航属性的缓存
private readonly List<MyEntity> _entityCache = new List<MyEntity>(); // Select子句
private readonly List<SelectResolveResult> _selectProperties = new List<SelectResolveResult>(); // 主表信息
private readonly MyEntity _masterEntity; // 查询需要的参数
private readonly MyDbParameters _parameters = new MyDbParameters(); // 是否已经调用过Where方法
private bool _hasInitWhere; // 拼接好的where子句
private string _where; // 拼接好的order by子句
private string _orderBy; // 构造方法
public MyQueryable(string connectionString)
{
_masterEntity = MyEntityContainer.Get(typeof(T));
_connectionString = connectionString;
} #region Include
public MyQueryable<T> Include<TProperty>(Expression<Func<T, TProperty>> expression) where TProperty : IEntity
{
if (expression.Body.NodeType == ExpressionType.MemberAccess)
{
var memberExpr = (MemberExpression)expression.Body;
if (memberExpr.Expression != null &&
memberExpr.Expression.NodeType == ExpressionType.Parameter &&
memberExpr.Member.GetType().IsClass)
{
_includeProperties.TryAdd(memberExpr.Member.Name, new string[]{});
}
} return this;
} public MyQueryable<T> Include<TProperty>(
Expression<Func<T, TProperty>> property,
Expression<Func<TProperty, object>> fields) where TProperty : IEntity
{
if (property.Body.NodeType == ExpressionType.MemberAccess)
{
var visitor = new ObjectMemberVisitor();
visitor.Visit(property);
var member = visitor.GetPropertyList().First(); visitor.Clear();
visitor.Visit(fields);
var fieldList = visitor.GetPropertyList(); _includeProperties.TryAdd(member, fieldList.ToArray());
} return this;
} public MyQueryable<T> Include(string navPropertyName)
{
var property = _masterEntity.Properties.Single(p => p.Name == navPropertyName);
if (property != null)
{
if (property.JoinAble)
{
_includeProperties.Add(property.Name, new string[]{});
}
}
return this;
} public MyQueryable<T> Include(string navPropertyName, string[] fields)
{
var property = _masterEntity.Properties.Single(p => p.Name == navPropertyName);
if (property != null)
{
if (property.JoinAble)
{
_includeProperties.Add(property.Name, fields);
}
}
return this;
}
#endregion #region Where
public MyQueryable<T> Where(Expression<Func<T, bool>> expr)
{
if (_hasInitWhere)
{
throw new ArgumentException("每个查询只能调用一次Where方法");
}
_hasInitWhere = true; var condition = new QueryConditionResolver<T>(_masterEntity);
var result = condition.Resolve(expr.Body);
_where = result.Condition;
_parameters.AddParameters(result.Parameters);
_entityCache.AddRange(result.NavPropertyList);
_whereProperties = result.NavPropertyList.Select(p => p.Name).ToList(); return this;
}
#endregion #region OrderBy,ThenOrderBy
public MyQueryable<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> expression,
MyDbOrderBy orderBy = MyDbOrderBy.Asc)
{
if (expression.Body.NodeType == ExpressionType.MemberAccess)
{
_orderBy = GetOrderByString((MemberExpression)expression.Body);
if (orderBy == MyDbOrderBy.Desc)
{
_orderBy += " DESC";
}
} return this;
} public MyQueryable<T> ThenOrderBy<TProperty>(Expression<Func<T, TProperty>> expression,
MyDbOrderBy orderBy = MyDbOrderBy.Asc)
{
if (string.IsNullOrWhiteSpace(_orderBy))
{
throw new ArgumentNullException(nameof(_orderBy), "排序字段为空,必须先调用OrderBy或OrderByDesc才能调用此方法");
}
if (expression.Body.NodeType == ExpressionType.MemberAccess)
{
_orderBy += "," + GetOrderByString((MemberExpression)expression.Body);
if (orderBy == MyDbOrderBy.Desc)
{
_orderBy += " DESC";
}
} return this;
}
#endregion #region Select public MySelect<TTarget> Select<TTarget>(Expression<Func<T, object>> expression)
{
var visitor = new SelectExpressionResolver();
visitor.Visit(expression);
_selectProperties.AddRange(visitor.GetPropertyList());
return new MySelect<TTarget>(_connectionString, GetFields(), GetFrom(), _where, _parameters, _orderBy);
} #endregion #region 输出
public List<T> ToList()
{
var fields = GetFields();
var from = GetFrom(); var sqlBuilder = new SqlServerBuilder();
var sql = sqlBuilder.Select(from, fields, _where, _orderBy); var visitor = new SqlDataReaderConverter<T>();
List<T> result;
using (var conn = new SqlConnection(_connectionString))
{
var command = new SqlCommand(sql, conn);
command.Parameters.AddRange(_parameters.Parameters);
conn.Open();
using (var sdr = command.ExecuteReader())
{
result = visitor.ConvertToEntityList(sdr);
}
} return result;
} public List<T> ToPageList(int pageIndex, int pageSize, out int recordCount)
{
var fields = GetFields();
var from = GetFrom();
recordCount = ; var sqlBuilder = new SqlServerBuilder();
var sql = sqlBuilder.PagingSelect(from, fields, _where, _orderBy, pageIndex, pageSize); var command = new SqlCommand(sql);
command.Parameters.AddRange(_parameters.Parameters);
var param = new SqlParameter("@RecordCount", SqlDbType.Int) { Direction = ParameterDirection.Output };
command.Parameters.Add(param); List<T> result; using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
command.Connection = conn;
using (var sdr = command.ExecuteReader())
{
var handler = new SqlDataReaderConverter<T>(_includeProperties.Select(p => p.Key).ToArray());
result = handler.ConvertToEntityList(sdr);
}
} recordCount = (int)param.Value;
return result;
} public T FirstOrDefault()
{
var fields = GetFields();
var from = GetFrom(); var sqlBuilder = new SqlServerBuilder();
var sql = sqlBuilder.Select(from, fields, _where, _orderBy, ); using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
var command = new SqlCommand(sql, conn);
command.Parameters.AddRange(_parameters.Parameters);
var sdr = command.ExecuteReader(); var handler = new SqlDataReaderConverter<T>(_includeProperties.Select(p => p.Key).ToArray());
return handler.ConvertToEntity2(sdr);
}
}
#endregion #region 辅助方法 /// 把要用到的导航属性的MyEntity缓存到一个List里,不需要每次都要到字典中获取
private MyEntity GetIncludePropertyEntityInfo(Type type)
{
var entity = _entityCache.FirstOrDefault(e => e.Name == type.FullName); if (entity != null) return entity; entity = MyEntityContainer.Get(type);
_entityCache.Add(entity);
return entity;
} // 获取Select子句
public string GetFields()
{
if (_selectProperties.Count == )
{
var masterFields = string.Join(
",",
_masterEntity
.Properties
.Where(p => p.IsMap)
.Select(p => $"[{_masterEntity.TableName}].[{p.FieldName}] AS [{p.Name}]")
); if (_includeProperties.Count > )
{
var sb = new StringBuilder(masterFields);
sb.Append(",");
var includeProperties = _includeProperties.OrderBy(i => i); foreach (var property in includeProperties)
{
var prop = _masterEntity.Properties.Single(p => p.Name == property.Key);
var propEntity = GetIncludePropertyEntityInfo(prop.PropertyInfo.PropertyType);
if (property.Value.Length == )
{
sb.Append(
string.Join(",",
propEntity.Properties.Where(p => p.IsMap).Select(p =>
$"[{propEntity.TableName}].[{p.FieldName}] AS [{property.Key}_{p.Name}]"))
);
}
else
{
sb.Append(
string.Join(",",
propEntity.Properties.Where(p =>
p.IsMap && property.Value.Contains(p.Name))
.Select(p =>
$"[{propEntity.TableName}].[{p.FieldName}] AS [{property.Key}_{p.Name}]"))
);
}
} return sb.ToString();
} return masterFields;
}
else
{
_includeProperties.Clear();
var sb = new StringBuilder();
foreach (var property in _selectProperties)
{
if (string.IsNullOrWhiteSpace(property.FieldName))
{
var prop = _masterEntity.Properties.Single(p => p.Name == property.PropertyName);
if (prop != null)
{
sb.Append($",[{_masterEntity.TableName}].[{prop.FieldName}] AS [{property.MemberName}]");
}
}
else
{
if (_masterEntity.Properties.Any(p => p.Name == property.PropertyName))
{
_includeProperties.Add(property.PropertyName, new string[] {});
var prop = _masterEntity.Properties.Single(p => p.Name == property.PropertyName);
var propEntity = GetIncludePropertyEntityInfo(prop.PropertyInfo.PropertyType); var field = propEntity.Properties.Single(p => p.Name == property.FieldName);
if (field != null)
{
sb.Append(
$",[{property.PropertyName}].[{field.FieldName}] AS [{property.MemberName}]");
}
}
}
} return sb.Remove(, ).ToString();
}
} // 获取From子句
public string GetFrom()
{
var masterTable = $"[{_masterEntity.TableName}]";
var allJoinProperties = _includeProperties.Select(p => p.Key).Concat(_whereProperties).Distinct().ToList(); if (allJoinProperties.Any())
{
var sb = new StringBuilder(masterTable);
foreach (var property in allJoinProperties)
{
var prop = _masterEntity.Properties.Single(p => p.Name == property);
if (prop != null)
{
var propEntity = GetIncludePropertyEntityInfo(prop.PropertyInfo.PropertyType);
sb.Append($" LEFT JOIN [{propEntity.TableName}] AS [{property}] ON [{_masterEntity.TableName}].[{prop.ForeignKey}]=[{propEntity.TableName}].[{propEntity.KeyColumn}]");
}
} return sb.ToString();
} return masterTable;
} // 获取OrderBy子句
private string GetOrderByString(MemberExpression expression)
{
expression.GetRootType(out var stack);
if (stack.Count == )
{
var propName = stack.Pop();
var prop = _masterEntity.Properties.Single(p => p.Name == propName);
return $"[{_masterEntity.TableName}].[{prop.FieldName}]";
} if (stack.Count == )
{
var slavePropName = stack.Pop();
var propertyName = stack.Pop(); var masterProp = _masterEntity.Properties.Single(p => p.Name == propertyName);
var slaveEntity = GetIncludePropertyEntityInfo(masterProp.PropertyInfo.PropertyType);
var slaveProperty = slaveEntity.Properties.Single(p => p.Name == slavePropName); return $"[{masterProp.Name}].[{slaveProperty.FieldName}]";
} return string.Empty;
} #endregion
}
}

二、按需查询 Select<T>()

using MyOrm.DbParameters;
using MyOrm.Mappers;
using MyOrm.SqlBuilder;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient; namespace MyOrm.Queryable
{
public class MySelect<T>
{
private readonly string _connectionString;
private readonly string _fields;
private readonly string _table;
private readonly string _where;
private readonly string _orderBy;
private readonly MyDbParameters _parameters; public MySelect(string connectionString, string fields, string table, string where, MyDbParameters dbParameters, string orderBy)
{
_fields = fields;
_table = table;
_where = where;
_parameters = dbParameters;
_orderBy = orderBy;
_connectionString = connectionString;
} public List<T> ToList()
{ var sqlBuilder = new SqlServerBuilder();
var sql = sqlBuilder.Select(_table, _fields, _where, _orderBy); var visitor = new SqlDataReaderMapper();
List<T> result;
using (var conn = new SqlConnection(_connectionString))
{
var command = new SqlCommand(sql, conn);
command.Parameters.AddRange(_parameters.Parameters);
conn.Open();
using (var sdr = command.ExecuteReader())
{
result = visitor.ConvertToList<T>(sdr);
}
} return result;
} //public List<dynamic> DynamicList()
//{
// var sqlBuilder = new SqlServerBuilder();
// var sql = sqlBuilder.Select(_table, _fields, _where, _orderBy); // var visitor = new SqlDataReaderMapper();
// List<dynamic> result;
// using (var conn = new SqlConnection(_connectionString))
// {
// var command = new SqlCommand(sql, conn);
// command.Parameters.AddRange(_parameters.Parameters);
// conn.Open();
// using (var sdr = command.ExecuteReader())
// {
// result = visitor.ConvertToList(sdr);
// }
// } // return result;
//} public List<T> ToPageList(int pageIndex, int pageSize, out int recordCount)
{
recordCount = ; var sqlBuilder = new SqlServerBuilder();
var sql = sqlBuilder.PagingSelect2008(_table, _fields, _where, _orderBy, pageIndex, pageSize); var command = new SqlCommand(sql);
command.Parameters.AddRange(_parameters.Parameters);
var param = new SqlParameter("@RecordCount", SqlDbType.Int) { Direction = ParameterDirection.Output };
command.Parameters.Add(param); List<T> result; using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
command.Connection = conn;
using (var sdr = command.ExecuteReader())
{
var handler = new SqlDataReaderMapper();
result = handler.ConvertToList<T>(sdr);
}
} recordCount = (int)param.Value;
return result;
} //public List<dynamic> ToPageListDynamic(int pageIndex, int pageSize, out int recordCount)
//{
// recordCount = 0; // var sqlBuilder = new SqlServerBuilder();
// var sql = sqlBuilder.PagingSelect2008(_table, _fields, _where, _orderBy, pageIndex, pageSize); // var command = new SqlCommand(sql);
// command.Parameters.AddRange(_parameters.Parameters);
// var param = new SqlParameter("@RecordCount", SqlDbType.Int) {Direction = ParameterDirection.Output};
// command.Parameters.Add(param); // List<dynamic> result; // using (var conn = new SqlConnection(_connectionString))
// {
// conn.Open();
// command.Connection = conn;
// using (var sdr = command.ExecuteReader())
// {
// var handler = new SqlDataReaderMapper();
// result = handler.ConvertToList(sdr);
// }
// } // recordCount = (int) param.Value;
// return result;
//} public T FirstOrDefault()
{
var sqlBuilder = new SqlServerBuilder();
var sql = sqlBuilder.Select(_table, _fields, _where, _orderBy, ); using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
var command = new SqlCommand(sql, conn);
command.Parameters.AddRange(_parameters.Parameters);
var sdr = command.ExecuteReader(); var handler = new SqlDataReaderMapper();
return handler.ConvertToEntity<T>(sdr);
}
} //public dynamic FirstOrDefaultDynamic()
//{
// var sqlBuilder = new SqlServerBuilder();
// var sql = sqlBuilder.Select(_table, _fields, _where, _orderBy, 1); // using (var conn = new SqlConnection(_connectionString))
// {
// conn.Open();
// var command = new SqlCommand(sql, conn);
// command.Parameters.AddRange(_parameters.Parameters);
// var sdr = command.ExecuteReader(); // var handler = new SqlDataReaderMapper();
// return handler.ConvertToEntity(sdr);
// }
//}
}
}

最新文章

  1. XV Open Cup named after E.V. Pankratiev. GP of Tatarstan
  2. 《Python标准库》 目录
  3. 三、Android学习第三天——Activity的布局初步介绍(转)
  4. python的ujson与simplejson
  5. IOS 杂笔-13(appearance的巧妙使用)
  6. ectouch第五讲 之表
  7. crud的意识
  8. VS2012中的全部预定义键盘快捷键列表
  9. nginx filter
  10. PostgreSQL学习手册(常用数据类型)
  11. C#进阶系列——使用Advanced Installer制作IIS安装包(一:配置IIS和Web.config)
  12. linux 部署jenkins
  13. android studio 2.32躺坑记
  14. 关于redis实现分布式锁
  15. ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接
  16. 使用miniconda创建python虚拟环境
  17. form转化json
  18. Docker(二十)-Docker容器CPU、memory资源限制
  19. 修复Mysql主从不同步shell
  20. 【gRPC使用问题2】按照问题1操作生成出来的代码,import的proto内定义的message未生成出来

热门文章

  1. ORA-00600: internal error code, arguments: [6749], [3], [12602196]
  2. SpringBoot_Exception_01_No plugin found for prefix &#39;spring-boto&#39; in the current project
  3. Workerman安装流程
  4. super.onCreate(savedInstanceState) 以及onCreate(Bundle savedInstanceState, PersistableBundle persistentState)
  5. Spring笔记05(Spring JDBC三种数据源和ORM框架的映射)
  6. MySQL_活动期间单笔订单最高的且满600元 判别是重激活客户还是10月注册客户_20161031
  7. 「LOJ#6121」「网络流 24 题」孤岛营救问题(BFS
  8. 自己实现的vector
  9. 微信开放平台开发-授权、全网发布(PHP)
  10. VijosP1180:选课