From baf6d768a4d3ed1b9acc447d742db08e7fdc2ea5 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Sat, 31 Aug 2019 03:00:17 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20Aop.AuditValue=20?= =?UTF-8?q?=E4=B8=8E=20FreeSql.Repository=20=E4=B8=BB=E9=94=AE=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=AE=A1=E7=90=86=E7=9A=84=E5=86=B2=E7=AA=81=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.DbContext/DbSet/DbSet.cs | 2 + FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml | 147 ++++++++++++++++++ .../FreeSql.Tests/Other/EntityBase.cs | 84 ++++++++++ FreeSql.Tests/FreeSql.Tests/Other/IEntity.cs | 21 +++ .../FreeSql.Tests/Other/IdentityType.cs | 16 ++ .../FreeSql.Tests/Other/SystemUser.cs | 60 +++++++ .../Other/SystemUserAuthentication.cs | 46 ++++++ FreeSql.Tests/FreeSql.Tests/UnitTest1.cs | 49 ++++++ FreeSql/FreeSql.xml | 2 +- FreeSql/Interface/IAop.cs | 10 +- .../Internal/CommonProvider/InsertProvider.cs | 52 +++++-- .../Internal/CommonProvider/UpdateProvider.cs | 48 ++++-- FreeSql/Internal/Model/ColumnInfo.cs | 20 +-- .../Curd/OracleInsert.cs | 9 -- 14 files changed, 514 insertions(+), 52 deletions(-) create mode 100644 FreeSql.Tests/FreeSql.Tests/Other/EntityBase.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Other/IEntity.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Other/IdentityType.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Other/SystemUser.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Other/SystemUserAuthentication.cs diff --git a/FreeSql.DbContext/DbSet/DbSet.cs b/FreeSql.DbContext/DbSet/DbSet.cs index 9a5d208e..32c69096 100644 --- a/FreeSql.DbContext/DbSet/DbSet.cs +++ b/FreeSql.DbContext/DbSet/DbSet.cs @@ -210,6 +210,7 @@ namespace FreeSql if (isThrow) throw new Exception($"不可添加,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); return false; } + FreeSql.Internal.CommonProvider.InsertProvider.AuditDataValue(this, data, _db.Orm, _table); var key = _db.Orm.GetEntityKeyString(_entityType, data, true); if (string.IsNullOrEmpty(key)) { @@ -269,6 +270,7 @@ namespace FreeSql if (isThrow) throw new Exception($"不可更新,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); return false; } + FreeSql.Internal.CommonProvider.UpdateProvider.AuditDataValue(this, data, _db.Orm, _table); var key = _db.Orm.GetEntityKeyString(_entityType, data, false); if (string.IsNullOrEmpty(key)) { diff --git a/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml b/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml index 52359271..6f593095 100644 --- a/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml +++ b/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml @@ -199,5 +199,152 @@ 创建日期 + + + 实体类基类 + + + + + 初始化一个类型的新实例 + + + + + 获取或设置主键 + + + + + 创建时间 + + + + + 判断两个实体是否是同一数据记录的实体 + + 要比较的实体信息 + + + + + 实体Id是否相等 + + + + + 用作特定类型的哈希函数 + + + 当前 的哈希代码。
+ 如果Idnull则返回0, + 如果不为null则返回Id对应的哈希值 +
+
+ + + 数据模型接口 + + + + + 实体唯一标识,主键 + + + + + 创建时间 + + + + + 登录类型 + + + + + 用户表 + + + + + 显示名称 + + + + + 真实名称 + + + + + 性别 + + + + + 生日 + + + + + 头像URL地址 + + + + + 备注 + + + + + 启用标志 + + + + + 删除标志 + + + + + 所属用户认证记录 + + + + + 用户认证表 + + + + + 用户表ID + + + + + 用户 + + + + + 登录类型 + + + + + 登录标识 + + + + + 登录凭证 + + + + + 验证标志 + + diff --git a/FreeSql.Tests/FreeSql.Tests/Other/EntityBase.cs b/FreeSql.Tests/FreeSql.Tests/Other/EntityBase.cs new file mode 100644 index 00000000..06309501 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Other/EntityBase.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; + +namespace Zeus.Utility.Entity +{ + /// + /// 实体类基类 + /// + public abstract class EntityBase : IEntity where TKey : IEquatable + { + /// + /// 初始化一个类型的新实例 + /// + protected EntityBase() + { + + } + + /// + /// 获取或设置主键 + /// + [Key] + public virtual TKey ID { get; set; } + + /// + /// 创建时间 + /// + public virtual DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 判断两个实体是否是同一数据记录的实体 + /// + /// 要比较的实体信息 + /// + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (!(obj is EntityBase entity)) + { + return false; + } + return IsKeyEqual(entity.ID, ID); + } + + /// + /// 实体Id是否相等 + /// + public static bool IsKeyEqual(TKey id1, TKey id2) + { + if (id1 == null && id2 == null) + { + return true; + } + if (id1 == null || id2 == null) + { + return false; + } + + return Equals(id1, id2); + } + + /// + /// 用作特定类型的哈希函数 + /// + /// + /// 当前 的哈希代码。
+ /// 如果Idnull则返回0, + /// 如果不为null则返回Id对应的哈希值 + ///
+ public override int GetHashCode() + { + if (ID == null) + { + return 0; + } + return ID.ToString().GetHashCode(); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Other/IEntity.cs b/FreeSql.Tests/FreeSql.Tests/Other/IEntity.cs new file mode 100644 index 00000000..5851fb4a --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Other/IEntity.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Zeus.Utility.Entity +{ + /// + /// 数据模型接口 + /// + public interface IEntity + { + /// + /// 实体唯一标识,主键 + /// + TKey ID { get; } + /// + /// 创建时间 + /// + DateTime CreatedAt { get; set; } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Other/IdentityType.cs b/FreeSql.Tests/FreeSql.Tests/Other/IdentityType.cs new file mode 100644 index 00000000..73c2622c --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Other/IdentityType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Zeus.Domain.Enum +{ + /// + /// 登录类型 + /// + public enum IdentityType + { + Account, + Email, + Mobile + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Other/SystemUser.cs b/FreeSql.Tests/FreeSql.Tests/Other/SystemUser.cs new file mode 100644 index 00000000..1b7a0a8a --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Other/SystemUser.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using FreeSql.DataAnnotations; +using Zeus.Utility.Entity; + +namespace Zeus +{ + /// + /// 用户表 + /// + [Table(Name = "system_user")] + public partial class SystemUser : EntityBase + { + /// + /// 显示名称 + /// + [Column(DbType = "varchar(20)", IsNullable = false, Unique = "UK_DisplayName")] + public string DisplayName { get; set; } + /// + /// 真实名称 + /// + [Column(DbType = "varchar(20)")] + public string RealName { get; set; } + /// + /// 性别 + /// + [Column(DbType = "varchar(2)")] + public string Gender { get; set; } + /// + /// 生日 + /// + [Column(DbType = "datetime")] + public DateTime? Birthday { get; set; } + /// + /// 头像URL地址 + /// + [Column(DbType = "varchar(200)")] + public string AvaterURL { get; set; } + /// + /// 备注 + /// + [Column(DbType = "varchar(500)")] + public string Remark { get; set; } + /// + /// 启用标志 + /// + [Column(DbType = "bit(1)", IsNullable = false)] + public bool IsEnabled { get; set; } + /// + /// 删除标志 + /// + [Column(DbType = "bit(1)", IsNullable = false)] + public bool IsDeleted { get; set; } + /// + /// 所属用户认证记录 + /// + [Navigate("SystemUserID")] + public ICollection SystemUserAuthentication_List { get; set; } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Other/SystemUserAuthentication.cs b/FreeSql.Tests/FreeSql.Tests/Other/SystemUserAuthentication.cs new file mode 100644 index 00000000..5da122f7 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Other/SystemUserAuthentication.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using FreeSql.DataAnnotations; +using Zeus.Domain.Enum; +using Zeus.Utility.Entity; + +namespace Zeus +{ + /// + /// 用户认证表 + /// + [Table(Name = "system_user_authentication")] + public partial class SystemUserAuthentication : EntityBase + { + /// + /// 用户表ID + /// + [Column(DbType = "bigint(20)", IsNullable = false)] + public long SystemUserID { get; set; } + /// + /// 用户 + /// + [Navigate("SystemUserID")] + public SystemUser SystemUser { get; set; } + /// + /// 登录类型 + /// + [Column(DbType = "varchar(10)", MapType = typeof(string), IsNullable = false)] + public IdentityType IdentityType { get; set; } + /// + /// 登录标识 + /// + [Column(DbType = "varchar(50)", IsNullable = false, Unique = "UK_Identifier")] + public string Identifier { get; set; } + /// + /// 登录凭证 + /// + [Column(DbType = "varchar(50)", IsNullable = false)] + public string Credential { get; set; } + /// + /// 验证标志 + /// + [Column(DbType = "bit(1)", IsNullable = false)] + public bool IsVerified { get; set; } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs index 6d8081d5..71b6e582 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs @@ -11,6 +11,10 @@ using System.Linq.Expressions; using System.Threading.Tasks; using System.Collections; using System.Diagnostics; +using Zeus; +using Zeus.Domain.Enum; +using System.ComponentModel.DataAnnotations; +using System.Reflection; namespace FreeSql.Tests { @@ -345,9 +349,54 @@ namespace FreeSql.Tests } public static int GetUNIX_TIMESTAMP() => 0; + + private List GetSystemUser() + { + SystemUser user = new SystemUser + { + DisplayName = "系统管理员", + RealName = "系统管理员", + Gender = "男", + Birthday = new DateTime(1984, 7, 1), + IsEnabled = true, + IsDeleted = false, + Remark = "禁止删除", + SystemUserAuthentication_List = new List() + }; + user.SystemUserAuthentication_List.Add(new SystemUserAuthentication() + { + IdentityType = IdentityType.Account, + Identifier = "admin", + Credential = "HyrPNXuCBaqZU3QIJqP9eThOHpFfm9p+", + IsVerified = true + }); + user.SystemUserAuthentication_List.Add(new SystemUserAuthentication() + { + IdentityType = IdentityType.Mobile, + Identifier = "13580592001", + Credential = "HyrPNXuCBaqZU3QIJqP9eThOHpFfm9p+", + IsVerified = true + }); + var users = new List + { + user + }; + return users; + } + + [Fact] public void Test1() { + //g.mysql.Aop.AuditValue += (s, e) => + //{ + // if (e.Column.CsType == typeof(long) + // && e.Property.GetCustomAttribute(false) != null + // && e.Value?.ToString() == "0") + // e.Value = new Random().Next(); + //}; + //g.mysql.GetRepository().Insert(GetSystemUser()); + g.mysql.Aop.ParseExpression += new EventHandler((s, e) => { if (e.Expression.NodeType == ExpressionType.Call && (e.Expression as MethodCallExpression).Method.Name == "GetUNIX_TIMESTAMP") diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index be8774fe..dc1ed173 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -2164,7 +2164,7 @@ 耗时(单位:毫秒) - + 类型 diff --git a/FreeSql/Interface/IAop.cs b/FreeSql/Interface/IAop.cs index 5a910569..cb8a4043 100644 --- a/FreeSql/Interface/IAop.cs +++ b/FreeSql/Interface/IAop.cs @@ -273,18 +273,18 @@ namespace FreeSql.Aop public class AuditValueEventArgs : EventArgs { - public AuditValueEventArgs(AutoValueType autoValueType, ColumnInfo column, PropertyInfo property, object value) + public AuditValueEventArgs(AuditValueType autoValueType, ColumnInfo column, PropertyInfo property, object value) { - this.AutoValueType = autoValueType; + this.AuditValueType = autoValueType; this.Column = column; this.Property = property; - this.Value = value; + this._value = value; } /// /// 类型 /// - public AutoValueType AutoValueType { get; } + public AuditValueType AuditValueType { get; } /// /// 属性列的元数据 /// @@ -308,5 +308,5 @@ namespace FreeSql.Aop private object _value; public bool IsChanged { get; private set; } } - public enum AutoValueType { Update, Insert } + public enum AuditValueType { Update, Insert } } \ No newline at end of file diff --git a/FreeSql/Internal/CommonProvider/InsertProvider.cs b/FreeSql/Internal/CommonProvider/InsertProvider.cs index 70210226..b41e4cd3 100644 --- a/FreeSql/Internal/CommonProvider/InsertProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertProvider.cs @@ -71,19 +71,56 @@ namespace FreeSql.Internal.CommonProvider public IInsert AppendData(T1 source) { - if (source != null) _source.Add(source); + if (source != null) + { + AuditDataValue(this, source, _orm, _table); + _source.Add(source); + } return this; } public IInsert AppendData(T1[] source) { - if (source != null) _source.AddRange(source); + if (source != null) + { + AuditDataValue(this, source, _orm, _table); + _source.AddRange(source); + } return this; } public IInsert AppendData(IEnumerable source) { - if (source != null) _source.AddRange(source.Where(a => a != null)); + if (source != null) + { + source = source.Where(a => a != null).ToList(); + AuditDataValue(this, source, _orm, _table); + _source.AddRange(source); + + } return this; } + public static void AuditDataValue(object sender, IEnumerable data, IFreeSql orm, TableInfo table) + { + if (data?.Any() != true) return; + foreach (var d in data) + AuditDataValue(sender, d, orm, table); + } + public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table) + { + if (data == null) return; + foreach (var col in table.Columns.Values) + { + object val = col.GetMapValue(data); + if (col.Attribute.IsPrimary && col.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) && (val == null || (Guid)val == Guid.Empty)) + col.SetMapValue(data, val = FreeUtil.NewMongodbId()); + if (orm.Aop.AuditValue != null) + { + var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Insert, col, table.Properties[col.CsName], val); + orm.Aop.AuditValue(sender, auditArgs); + if (auditArgs.IsChanged) + col.SetMapValue(data, val = auditArgs.Value); + } + } + } #region 参数化数据限制,或values数量限制 protected List[] SplitSource(int valuesLimit, int parameterLimit) @@ -557,15 +594,6 @@ namespace FreeSql.Internal.CommonProvider if (colidx2 > 0) sb.Append(", "); object val = col.GetMapValue(d); - if (col.Attribute.IsPrimary && col.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) && (val == null || (Guid)val == Guid.Empty)) - col.SetMapValue(d, val = FreeUtil.NewMongodbId()); - if (_orm.Aop.AuditValue != null) - { - var auditArgs = new Aop.AuditValueEventArgs(Aop.AutoValueType.Insert, col, _table.Properties[col.CsName], val); - _orm.Aop.AuditValue(this, auditArgs); - if (auditArgs.IsChanged) - col.SetMapValue(d, val = auditArgs.Value); - } if (_noneParameter) sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val)); else diff --git a/FreeSql/Internal/CommonProvider/UpdateProvider.cs b/FreeSql/Internal/CommonProvider/UpdateProvider.cs index 5589ede6..ce358480 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -401,10 +401,42 @@ namespace FreeSql.Internal.CommonProvider return this; } + public static void AuditDataValue(object sender, IEnumerable data, IFreeSql orm, TableInfo table) + { + if (data?.Any() != true) return; + if (orm.Aop.AuditValue == null) return; + foreach (var d in data) + { + if (d == null) continue; + foreach (var col in table.Columns.Values) + { + object val = col.GetMapValue(d); + var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val); + orm.Aop.AuditValue(sender, auditArgs); + if (auditArgs.IsChanged) + col.SetMapValue(d, val = auditArgs.Value); + } + } + } + public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table) + { + if (orm.Aop.AuditValue == null) return; + if (data == null) return; + foreach (var col in table.Columns.Values) + { + object val = col.GetMapValue(data); + var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val); + orm.Aop.AuditValue(sender, auditArgs); + if (auditArgs.IsChanged) + col.SetMapValue(data, val = auditArgs.Value); + } + } + public IUpdate SetSource(T1 source) => this.SetSource(new[] { source }); public IUpdate SetSource(IEnumerable source) { if (source == null || source.Any() == false) return this; + AuditDataValue(this, source, _orm, _table); _source.AddRange(source.Where(a => a != null)); return this; } @@ -606,13 +638,6 @@ namespace FreeSql.Internal.CommonProvider if (colidx > 0) sb.Append(", "); sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = "); var val = col.GetMapValue(_source.First()); - if (_orm.Aop.AuditValue != null) - { - var auditArgs = new Aop.AuditValueEventArgs(Aop.AutoValueType.Update, col, _table.Properties[col.CsName], val); - _orm.Aop.AuditValue(this, auditArgs); - if (auditArgs.IsChanged) - col.SetMapValue(_source.First(), val = auditArgs.Value); - } if (_noneParameter) sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, val)); else @@ -629,7 +654,7 @@ namespace FreeSql.Internal.CommonProvider else if (_source.Count > 1) { //批量保存 Source if (_table.Primarys.Any() == false) return null; - + var caseWhen = new StringBuilder(); caseWhen.Append("CASE "); ToSqlCase(caseWhen, _table.Primarys); @@ -652,13 +677,6 @@ namespace FreeSql.Internal.CommonProvider ToSqlWhen(cwsb, _table.Primarys, d); cwsb.Append(" THEN "); var val = col.GetMapValue(d); - if (_orm.Aop.AuditValue != null) - { - var auditArgs = new Aop.AuditValueEventArgs(Aop.AutoValueType.Update, col, _table.Properties[col.CsName], val); - _orm.Aop.AuditValue(this, auditArgs); - if (auditArgs.IsChanged) - col.SetMapValue(_source.First(), val = auditArgs.Value); - } if (_noneParameter) cwsb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, val)); else diff --git a/FreeSql/Internal/Model/ColumnInfo.cs b/FreeSql/Internal/Model/ColumnInfo.cs index 8ff71303..fbc26e05 100644 --- a/FreeSql/Internal/Model/ColumnInfo.cs +++ b/FreeSql/Internal/Model/ColumnInfo.cs @@ -57,22 +57,22 @@ namespace FreeSql.Internal.Model var objExp = Expression.Parameter(typeof(object), "obj"); var valExp = Expression.Parameter(typeof(object), "val"); - if (Attribute.MapType == CsType) - return Expression.Lambda>( - Expression.Assign(Expression.MakeMemberAccess( - Expression.TypeAs(objExp, col.Table.Type), - Table.Properties[col.CsName] - ), Expression.Convert( - valExp, - Attribute.MapType)), objExp, valExp).Compile(); + //if (Attribute.MapType == CsType) + // return Expression.Lambda>( + // Expression.Assign(Expression.MakeMemberAccess( + // Expression.TypeAs(objExp, col.Table.Type), + // Table.Properties[col.CsName] + // ), Expression.Convert( + // valExp, + // Attribute.MapType)), objExp, valExp).Compile(); return Expression.Lambda>( Expression.Assign(Expression.MakeMemberAccess( Expression.TypeAs(objExp, col.Table.Type), Table.Properties[col.CsName] ), Expression.Convert( - Utils.GetDataReaderValueBlockExpression(Attribute.MapType, valExp), - Attribute.MapType)), objExp, valExp).Compile(); + Utils.GetDataReaderValueBlockExpression(CsType, valExp), + CsType)), objExp, valExp).Compile(); }); func(obj, val); } diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs index 97745f0f..61f68ec6 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs @@ -68,15 +68,6 @@ namespace FreeSql.Oracle.Curd if (colidx2 > 0) sb.Append(", "); object val = col.GetMapValue(d); - if (col.Attribute.IsPrimary && col.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) && (val == null || (Guid)val == Guid.Empty)) - col.SetMapValue(d, val = FreeUtil.NewMongodbId()); - if (_orm.Aop.AuditValue != null) - { - var auditArgs = new Aop.AuditValueEventArgs(Aop.AutoValueType.Insert, col, _table.Properties[col.CsName], val); - _orm.Aop.AuditValue(this, auditArgs); - if (auditArgs.IsChanged) - col.SetMapValue(d, val = auditArgs.Value); - } if (_noneParameter) sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val)); else