using System;
using System.Collections.Generic;
using CYQ.Data.Table;
using System.Reflection;
using CYQ.Data.Tool;
using CYQ.Data.SQL;
using System.Data;
using CYQ.Data.Aop;
using CYQ.Data.UI;
using CYQ.Data.Json;
namespace CYQ.Data.Orm
{
/////
///// ORM CodeFirst 字段来源
/////
//public enum FieldSource
//{
// ///
// /// 从实体属性来
// ///
// Property,
// ///
// /// 从数据库或文本数据来
// ///
// Data,
// ///
// /// 综合以上两者
// ///
// BothOfAll
//}
///
/// 简单ORM基类(无属性拦截,实体全量更新或插入)
///
public abstract class SimpleOrmBase : SimpleOrmBase where T : class
{
public new T Get(object where)
{
return base.Get(where);
}
public new List Select()
{
return base.Select();
}
public new List Select(int pageIndex, int pageSize)
{
return base.Select(pageIndex, pageSize);
}
public new List Select(int topN, string where)
{
return base.Select(topN, where);
}
public new List Select(string where)
{
return base.Select(where);
}
public new List Select(int pageIndex, int pageSize, string where)
{
return base.Select(pageIndex, pageSize, where);
}
public new List Select(int pageIndex, int pageSize, string where, out int count)
{
return base.Select(pageIndex, pageSize, where, out count);
}
}
internal class SimpleOrmBaseDefaultInstance : SimpleOrmBase
{ }
///
/// 简单ORM基类(无属性拦截,实体全量更新或插入)
///
public abstract class SimpleOrmBase : IDisposable
{
OrmBaseInfo _BaseInfo;
///
/// 获取 - 基类 ORM 的相关信息【Orm内部属性】
///
[JsonIgnore]
public OrmBaseInfo BaseInfo
{
get
{
if (_BaseInfo == null)
{
_BaseInfo = new OrmBaseInfo(Action);
}
return _BaseInfo;
}
}
internal MDataColumn Columns = null;
private bool _IsWriteLogOnError = true;
///
/// 标识是否允许写日志(默认true)
///
[JsonIgnore]
internal bool IsWriteLogOnError
{
set
{
_IsWriteLogOnError = value;
if (_Action != null && _Action.dalHelper != null)
{
_Action.dalHelper.IsWriteLogOnError = value;
}
}
}
///
/// 是否启用了AOP拦截设置字段值同步(默认false)
///
internal bool IsUseAop = false;
//private static FieldSource _FieldSource = FieldSource.BothOfAll;
/////
///// 字段来源(当字段变更时,可以设置此属性来切换更新)
/////
//public static FieldSource FieldSource
//{
// get
// {
// return _FieldSource;
// }
// set
// {
// _FieldSource = value;
// }
//}
Object entity;//实体对象
Type typeInfo;//实体对象类型
private MAction _Action;
[JsonIgnore]
internal MAction Action
{
get
{
//conn 为 null,则自动取值,为空则人为传空,不处理。
if (_Action == null && _conn != "")
{
SetDelayInit(_entityInstance, _tableName, _conn);//延迟加载
if (_Action != null && _Action.dalHelper != null)
{
_Action.dalHelper.IsWriteLogOnError = _IsWriteLogOnError;
}
}
return _Action;
}
}
///
/// Whether to allow manual insertion of ids for self-incrementing primary key identification
///自增主键标识的,是否允许手动插入id
///
[JsonIgnore]
public bool AllowInsertID
{
get
{
if (Action != null)
{
return Action.AllowInsertID;
}
return false;
}
set
{
if (Action != null)
{
Action.AllowInsertID = value;
}
}
}
///
/// 构造函数
///
public SimpleOrmBase()
{
}
///
/// 设置参数化
///
public SimpleOrmBase SetPara(object paraName, object value)
{
if (Action != null)
{
Action.SetPara(paraName, value);
}
return this;
}
///
/// 设置参数化
///
public SimpleOrmBase SetPara(object paraName, object value, DbType dbType)
{
if (Action != null)
{
Action.SetPara(paraName, value, dbType);
}
return this;
}
///
/// Sets a custom expression for the Update operation.
/// 为Update操作设置自定义表达式。
///
/// as:"a=a+1"如:"a=a+1"
public SimpleOrmBase SetExpression(string updateExpression)
{
if (Action != null)
{
Action.SetExpression(updateExpression);
}
return this;
}
///
/// 设置Aop状态
///
///
public SimpleOrmBase SetAopState(AopOp op)
{
if (Action != null)
{
Action.SetAopState(op);
}
return this;
}
///
/// 初始化状态[继承此基类的实体在构造函数中需调用此方法]
///
/// 实体对象,一般写:this
protected void SetInit(Object entityInstance)
{
SetInit(entityInstance, null, null, true);
}
///
/// 初始化状态[继承此基类的实体在构造函数中需调用此方法]
///
/// 实体对象,一般写:this
/// 表名,如:Users
protected void SetInit(Object entityInstance, string tableName)
{
SetInit(entityInstance, tableName, null, true);
}
///
/// 初始化状态[继承此基类的实体在构造函数中需调用此方法]
///
/// 实体对象,一般写:this
/// 表名,如:Users
/// 数据链接,单数据库时可写Null,或写默认链接配置项:"Conn",或直接数据库链接字符串
protected void SetInit(Object entityInstance, string tableName, string conn)
{
SetInit(entityInstance, tableName, conn, true);
}
///
/// 初始化状态[继承此基类的实体在构造函数中需调用此方法]
///
/// 实体对象,一般写:this
/// 表名,如:Users
/// 数据链接,单数据库时可写Null,或写默认链接配置项:"Conn",或直接数据库链接字符串
/// 当执行发生异常时,是否输出日志
protected void SetInit(Object entityInstance, string tableName, string conn, bool isWriteLogOnError)
{
_entityInstance = entityInstance;
_tableName = tableName;
_conn = conn;
_IsWriteLogOnError = isWriteLogOnError;
}
private object _entityInstance;
private string _tableName = null;
private string _conn = null;
///
/// 将原有的初始化改造成延时加载。
///
private void SetDelayInit(Object entityInstance, string tableName, string conn)
{
if (tableName == AppConfig.Log.TableName && string.IsNullOrEmpty(AppConfig.Log.Conn))
{
return;
}
//if (string.IsNullOrEmpty(conn))
//{
// //不设置链接,则忽略(当成普通的实体类)
// return;
//}
if (entityInstance == null) { entityInstance = this; }
entity = entityInstance;
typeInfo = entity.GetType();
try
{
if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(conn))
{
string tName, tConn;
tName = DBFast.GetTableName(typeInfo, out tConn);
if (string.IsNullOrEmpty(tableName)) { tableName = tName; }
if (string.IsNullOrEmpty(conn)) { conn = tConn; }
}
string errMsg = string.Empty;
Columns = DBTool.GetColumns(tableName, conn, out errMsg);//内部链接错误时抛异常。
if (Columns == null || Columns.Count == 0)
{
if (errMsg != string.Empty)
{
Error.Throw(errMsg);
}
Columns = TableSchema.GetColumnByType(typeInfo, conn);
ConnBean connBean = ConnBean.Create(conn);//下面指定链接,才不会在主从备时被切换到其它库。
if (connBean == null)
{
string err = "SimpleOrmBase.SetDelayInit ConnBean can't create by " + conn;
Log.Write(err, LogType.DataBase);
Error.Throw(err);
}
if (!DBTool.Exists(tableName, "U", connBean.ConnStringOrg))
{
lock (tableName)
{
if (!DBTool.Exists(tableName, "U", connBean.ConnStringOrg))
{
DBTool.ErrorMsg = null;
if (!DBTool.CreateTable(tableName, Columns, connBean.ConnStringOrg))
{
string err = "SimpleOrmBase :Create Table " + tableName + " Error:" + DBTool.ErrorMsg;
Log.Write(err, LogType.DataBase);
Error.Throw(err);
}
}
}
}
}
_Action = new MAction(Columns.ToRow(tableName), conn);
if (typeInfo.Name == "SysLogs")
{
_Action.SetAopState(Aop.AopOp.CloseAll);
}
}
catch (Exception err)
{
if (typeInfo.Name != "SysLogs")
{
Log.Write(err, LogType.DataBase);
}
Error.Throw(err.Message);
}
}
internal void SetInit2(Object entityInstance, string tableName, string conn, bool isWriteLogOnError)
{
SetInit(entityInstance, tableName, conn, isWriteLogOnError);
}
internal void Set(object key, object value)
{
if (Action != null)
{
Action.Set(key, value);
}
}
#region 基础增删改查 成员
#region 插入
///
/// 插入数据
///
public bool Insert()
{
return Insert(false, InsertOp.ID, false);
}
///
/// 插入数据
///
/// 插入选项
public bool Insert(InsertOp option)
{
return Insert(false, option, false);
}
///
/// 插入数据
///
/// 插入主键
public bool Insert(InsertOp option, bool insertID)
{
return Insert(false, option, insertID);
}
///
/// 插入数据
///
/// 是否自动获取值[自动从控件获取值,需要先调用this.UI.SetAutoPrefix或this.UI.SetAutoParentControl方法设置控件前缀]
public bool Insert(bool autoSetValue)
{
return Insert(autoSetValue, InsertOp.ID, false);
}
///
/// 插入数据
///
/// 是否自动获取值[自动从控件获取值,需要先调用this.UI.SetAutoPrefix或this.UI.SetAutoParentControl方法设置控件前缀]
public bool Insert(bool autoSetValue, InsertOp option)
{
return Insert(autoSetValue, option, false);
}
///
/// 插入数据
///
/// 是否自动获取值[自动从控件获取值,需要先调用this.UI.SetAutoPrefix或this.UI.SetAutoParentControl方法设置控件前缀]
/// 插入选项
/// 插入主键
public bool Insert(bool autoSetValue, InsertOp option, bool insertID)
{
if (Action == null)
{
return false;
}
if (autoSetValue)
{
Action.UI.GetAll(!insertID);
}
GetValueFromEntity();
Action.AllowInsertID = insertID;
bool result = Action.Insert(false, option);
if (autoSetValue || option != InsertOp.None)
{
SetValueToEntity();
}
return result;
}
#endregion
#region 更新
///
/// 更新数据(受影响行数>0才为true)
///
public bool Update()
{
return Update(null, false, null);
}
///
/// 更新数据(受影响行数>0才为true)
///
/// where条件,可直接传id的值如:[88],或传完整where条件如:[id=88 and name='路过秋天']
/// 指定仅更新的列名,多个用逗号分隔
///
public bool Update(object where, params string[] updateColumns)
{
return Update(where, false, updateColumns);
}
///
/// 更新数据(受影响行数>0才为true)
///
/// where条件,可直接传id的值如:[88],或传完整where条件如:[id=88 and name='路过秋天']
/// 是否自动获取值[自动从控件获取值,需要先调用this.UI.SetAutoPrefix或this.UI.SetAutoParentControl方法设置控件前缀]
public bool Update(object where, bool autoSetValue, params string[] updateColumns)
{
if (Action == null)
{
return false;
}
if (autoSetValue)
{
Action.UI.GetAll(false);
}
GetValueFromEntity();
if (updateColumns != null && updateColumns.Length > 0)
{
Action.Data.SetState(0);
if (updateColumns.Length == 1)
{
updateColumns = updateColumns[0].Split(',');
}
foreach (string item in updateColumns)
{
MDataCell cell = Action.Data[item];
if (cell != null)
{
cell.State = 2;
}
}
}
bool result = Action.Update(where) && Action.RecordsAffected > 0;
if (autoSetValue)
{
SetValueToEntity();
}
return result;
}
#endregion
#region 删除
///
/// 删除数据(受影响行数>0才为true)
///
public bool Delete()
{
return Delete(null);
}
///
/// 删除数据(受影响行数>0才为true)
///
/// where条件,可直接传id的值如:[88],或传完整where条件如:[id=88 and name='路过秋天']
public bool Delete(object where)
{
return Delete(where, false);
}
///
/// 删除数据(受影响行数>0才为true)
///
/// 当表存在删除字段,如:IsDeleted标识时,默认会转成更新,此标识可以强制设置为删除
///
public bool Delete(object where, bool isIgnoreDeleteField)
{
if (Action == null)
{
return false;
}
GetValueFromEntity();
return Action.Delete(where, isIgnoreDeleteField) && Action.RecordsAffected > 0;
}
#endregion
#region 查询
///
/// 查询1条数据
///
public bool Fill()
{
return Fill(null);
}
///
/// 查询1条数据
///
public bool Fill(object where)
{
if (Action == null)
{
return false;
}
bool result = Action.Fill(where);
if (result)
{
SetValueToEntity();
}
return result;
}
///
/// 查询一条数据并返回一个新的实例
///
///
///
public virtual T Get(object where) where T : class
{
if (Action != null)
{
bool result = Action.Fill(where);
if (result)
{
return Action.Data.ToEntity();
}
}
return default(T);
}
///
/// 列表查询
///
public virtual List Select() where T : class
{
int count = 0;
return Select(0, 0, null, out count);
}
///
/// 列表查询
///
/// 查询条件[可附带 order by 语句]
///
public virtual List Select(string where) where T : class
{
int count = 0;
return Select(0, 0, where, out count);
}
///
/// 列表查询
///
/// 查询几条
/// 查询条件[可附带 order by 语句]
///
public virtual List Select(int topN, string where) where T : class
{
int count = 0;
return Select(0, topN, where, out count);
}
public virtual List Select(int pageIndex, int pageSize) where T : class
{
int count = 0;
return Select(pageIndex, pageSize, null, out count);
}
public virtual List Select(int pageIndex, int pageSize, string where) where T : class
{
int count = 0;
return Select(pageIndex, pageSize, where, out count);
}
///
/// 带分布功能的选择[多条件查询,选择所有时只需把PageIndex/PageSize设置为0]
///
/// 第几页
/// 每页数量[为0时默认选择所有]
/// 查询条件[可附带 order by 语句]
/// 返回的记录总数
/// 指定返回的列
public virtual List Select(int pageIndex, int pageSize, string where, out int count) where T : class
{
if (Action == null)
{
count = 0;
return null;
}
return Action.SelectList(pageIndex, pageSize, where, out count);
}
internal MDataTable Select(int pageIndex, int pageSize, string where, out int count)
{
if (Action == null)
{
count = 0;
return null;
}
return Action.Select(pageIndex, pageSize, where, out count);
}
public SimpleOrmBase SetSelectColumns(params object[] columnNames)
{
if (Action != null)
{
Action.SetSelectColumns(columnNames);
}
return this;
}
///
/// 获取记录总数
///
public int GetCount()
{
if (Action == null)
{
return 0;
}
return Action.GetCount();
}
///
/// 获取记录总数
///
public int GetCount(object where)
{
if (Action == null)
{
return 0;
}
return Action.GetCount(where);
}
///
/// 查询是否存在指定的条件的数据
///
public bool Exists(object where)
{
if (Action == null)
{
return false;
}
return Action.Exists(where);
}
#endregion
///
/// 批量加载值(可从Json、实体对象、MDataRow、泛型字段等批量加载值)
///
/// json字符串或实体对象
public void LoadFrom(object jsonOrEntity)
{
LoadFrom(jsonOrEntity, BreakOp.None);
}
public void LoadFrom(object jsonOrEntity, BreakOp op)
{
MDataRow newValueRow = MDataRow.CreateFrom(jsonOrEntity, null, op);
if (Action != null)
{
Action.Data.LoadFrom(newValueRow);
}
List piList = ReflectTool.GetPropertyList(typeInfo);
foreach (PropertyInfo item in piList)
{
if (item.CanWrite)
{
MDataCell cell = newValueRow[item.Name];
if (cell != null && !cell.IsNull)
{
try
{
item.SetValue(entity, ConvertTool.ChangeType(cell.Value, item.PropertyType), null);
}
catch (Exception err)
{
Log.Write(err, LogType.Error);
}
}
}
}
}
#endregion
internal void SetValueToEntity()
{
SetValueToEntity(null, RowOp.IgnoreNull);
}
internal void SetValueToEntity(RowOp op)
{
SetValueToEntity(null, op);
}
internal void SetValueToEntity(string propName, RowOp op)
{
if (!string.IsNullOrEmpty(propName))
{
PropertyInfo pi = typeInfo.GetProperty(propName);
if (pi != null && pi.CanWrite)
{
MDataCell cell = Action.Data[propName];
if (cell != null && !cell.IsNull)
{
try
{
pi.SetValue(entity, cell.Value, null);
}
catch
{
}
}
}
}
else
{
if (Action != null)
{
Action.Data.SetToEntity(entity, op);
}
}
}
private void GetValueFromEntity()
{
if (!IsUseAop || AppConfig.IsNetCore)//ASPNETCore下,动态代理的Aop是无效的
{
MDataRow d = Action.Data;//先触发延时加载的。
MDataRow row = MDataRow.CreateFrom(entity);//以实体原有值为基础。
foreach (MDataCell cell in d)
{
MDataCell valueCell = row[cell.ColumnName];
if (valueCell == null || valueCell.IsNull)
{
continue;
}
if (cell.State == 2 && cell.Struct.ValueType.IsValueType && (valueCell.StringValue == "0" || valueCell.StringValue == DateTime.MinValue.ToString()))
{
continue;
}
cell.Value = valueCell.Value;
}
}
}
///
/// 清除(SetPara设置的)自定义参数
///
public void ClearPara()
{
if (_Action != null)
{
_Action.ClearPara();
}
}
///
/// 清空所有值
///
public void Clear()
{
if (_Action != null)
{
_Action.Data.Clear();
}
}
///
/// UI操作
///
[JsonIgnore]
public MActionUI UI
{
get
{
if (Action == null) { return null; }
if (Action.UI.IsOnAfterGetFromEventNull)
{
Action.UI.OnAfterGetFromEvent += new CYQ.Data.UI.MActionUI.OnAfterGetFrom(UI_OnAfterGetFromEvent);
}
return Action.UI;
}
}
void UI_OnAfterGetFromEvent(string propValue)
{
if (!string.IsNullOrEmpty(propValue))
{
SetValueToEntity(propValue, RowOp.IgnoreNull);
}
}
#region IDisposable 成员
///
/// 释放资源
///
public void Dispose()
{
if (_Action != null && !_Action.IsTransation)//ORM的事务,由全局控制,不在这里释放链接。
{
_Action.Dispose();
_Action = null;
}
}
#endregion
}
}