diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/MySqlAopTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/MySqlAopTest.cs new file mode 100644 index 00000000..2bec5373 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/MySqlAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.MySqlConnector +{ + public class MySqlAop + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var now = DateTime.Now; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now; + }; + g.mysql.Aop.AuditValue += audit; + + g.mysql.Insert(item).ExecuteAffrows(); + + g.mysql.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime.Date, now.Date); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/MySqlAopTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/MySqlAopTest.cs new file mode 100644 index 00000000..a154f0a5 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/MySql/MySqlAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.MySql +{ + public class MySqlAopTest + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var now = DateTime.Now; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now; + }; + g.mysql.Aop.AuditValue += audit; + + g.mysql.Insert(item).ExecuteAffrows(); + + g.mysql.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime.Date, now.Date); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/OracleAopTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/OracleAopTest.cs new file mode 100644 index 00000000..5a30b033 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/OracleAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.Oracle +{ + public class OracleAopTest + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var now = DateTime.Now; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now; + }; + g.oracle.Aop.AuditValue += audit; + + g.oracle.Insert(item).ExecuteAffrows(); + + g.oracle.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime.Date, now.Date); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLAopTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLAopTest.cs new file mode 100644 index 00000000..ad0e5140 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.PostgreSQL +{ + public class PostgreSQLAopTest + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var now = DateTime.Now; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now; + }; + g.pgsql.Aop.AuditValue += audit; + + g.pgsql.Insert(item).ExecuteAffrows(); + + g.pgsql.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime.Date, now.Date); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerAopTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerAopTest.cs new file mode 100644 index 00000000..3c8b4511 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.SqlServer +{ + public class SqlServerAopTest + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var now = DateTime.Now; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now; + }; + g.sqlserver.Aop.AuditValue += audit; + + g.sqlserver.Insert(item).ExecuteAffrows(); + + g.sqlserver.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime.Date, now.Date); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteAopTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteAopTest.cs new file mode 100644 index 00000000..5cddd046 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.Sqlite +{ + public class SqliteAopTest + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var now = DateTime.Now; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now; + }; + g.sqlite.Aop.AuditValue += audit; + + g.sqlite.Insert(item).ExecuteAffrows(); + + g.sqlite.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime.Date, now.Date); + } + } +} diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 14783b73..310ff7ed 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -2020,6 +2020,11 @@ CodeFirst迁移,执行完成触发 + + + Insert/Update自动值处理, e.Column.SetMapValue( + + 可重新装饰的引用数据 @@ -2145,6 +2150,26 @@ 耗时(单位:毫秒) + + + 类型 + + + + + 属性列的元数据 + + + + + 反射的属性信息 + + + + + 获取实体的属性值,也可以设置实体的属性新值 + + 【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改 diff --git a/FreeSql/Interface/IAop.cs b/FreeSql/Interface/IAop.cs index 4b777b2f..23cfd63e 100644 --- a/FreeSql/Interface/IAop.cs +++ b/FreeSql/Interface/IAop.cs @@ -1,5 +1,6 @@ using FreeSql.DataAnnotations; using FreeSql.DatabaseModel; +using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data.Common; @@ -53,6 +54,11 @@ namespace FreeSql /// CodeFirst迁移,执行完成触发 /// EventHandler SyncStructureAfter { get; set; } + + /// + /// Insert/Update自动值处理, e.Column.SetMapValue( + /// + EventHandler AuditValue { get; set; } } } @@ -264,4 +270,43 @@ namespace FreeSql.Aop /// public long ElapsedMilliseconds => this.Stopwatch.ElapsedMilliseconds; } + + public class AuditValueEventArgs : EventArgs + { + public AuditValueEventArgs(AutoValueType autoValueType, ColumnInfo column, PropertyInfo property, object value) + { + this.AutoValueType = autoValueType; + this.Column = column; + this.Property = property; + this.Value = value; + } + + /// + /// 类型 + /// + public AutoValueType AutoValueType { get; } + /// + /// 属性列的元数据 + /// + public ColumnInfo Column { get; } + /// + /// 反射的属性信息 + /// + public PropertyInfo Property { get; } + /// + /// 获取实体的属性值,也可以设置实体的属性新值 + /// + public object Value + { + get => _value; + set + { + _value = value; + this.IsChanged = true; + } + } + private object _value; + internal bool IsChanged { get; private set; } + } + public enum AutoValueType { Update, Insert } } \ No newline at end of file diff --git a/FreeSql/Internal/CommonProvider/AopProvider.cs b/FreeSql/Internal/CommonProvider/AopProvider.cs index 3f6d15b2..3312e50d 100644 --- a/FreeSql/Internal/CommonProvider/AopProvider.cs +++ b/FreeSql/Internal/CommonProvider/AopProvider.cs @@ -17,5 +17,6 @@ namespace FreeSql.Internal.CommonProvider public EventHandler CurdAfter { get; set; } public EventHandler SyncStructureBefore { get; set; } public EventHandler SyncStructureAfter { get; set; } + public EventHandler AuditValue { get; set; } } } diff --git a/FreeSql/Internal/CommonProvider/InsertProvider.cs b/FreeSql/Internal/CommonProvider/InsertProvider.cs index 04ae09d6..4a3da08e 100644 --- a/FreeSql/Internal/CommonProvider/InsertProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertProvider.cs @@ -559,6 +559,13 @@ namespace FreeSql.Internal.CommonProvider 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.Value != null) + 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 049e6cbd..4d2ac1f2 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -605,15 +605,20 @@ namespace FreeSql.Internal.CommonProvider { if (colidx > 0) sb.Append(", "); sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = "); - var value = col.GetMapValue(_source.First()); - if (_noneParameter) + var val = col.GetMapValue(_source.First()); + if (_orm.Aop.AuditValue != null) { - sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, value)); + var auditArgs = new Aop.AuditValueEventArgs(Aop.AutoValueType.Update, col, _table.Properties[col.CsName], val); + _orm.Aop.AuditValue(this, auditArgs); + if (auditArgs.Value != null) + col.SetMapValue(_source.First(), val = auditArgs.Value); } + if (_noneParameter) + sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, val)); else { sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"))); - _commonUtils.AppendParamter(_paramsSource, null, col.Attribute.MapType, value); + _commonUtils.AppendParamter(_paramsSource, null, col.Attribute.MapType, val); } ++colidx; } @@ -646,17 +651,22 @@ namespace FreeSql.Internal.CommonProvider cwsb.Append(" \r\nWHEN "); ToSqlWhen(cwsb, _table.Primarys, d); cwsb.Append(" THEN "); - var value = col.GetMapValue(d); - if (_noneParameter) + var val = col.GetMapValue(d); + if (_orm.Aop.AuditValue != null) { - cwsb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, value)); + var auditArgs = new Aop.AuditValueEventArgs(Aop.AutoValueType.Update, col, _table.Properties[col.CsName], val); + _orm.Aop.AuditValue(this, auditArgs); + if (auditArgs.Value != null) + col.SetMapValue(_source.First(), val = auditArgs.Value); } + if (_noneParameter) + cwsb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, val)); else { cwsb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"))); - _commonUtils.AppendParamter(_paramsSource, null, col.Attribute.MapType, value); + _commonUtils.AppendParamter(_paramsSource, null, col.Attribute.MapType, val); } - if (isnull == false) isnull = value == null || value == DBNull.Value; + if (isnull == false) isnull = val == null || val == DBNull.Value; } cwsb.Append(" END"); if (isnull == false) diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs index 79cc3192..6980bab6 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsert.cs @@ -70,6 +70,13 @@ namespace FreeSql.Oracle.Curd 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.Value != null) + col.SetMapValue(d, val = auditArgs.Value); + } if (_noneParameter) sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val)); else