From e2d33e943fb3140267c34aa2bfdfda4dde06c712 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Wed, 24 Apr 2019 15:09:32 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20ISelect.ToList(true)?= =?UTF-8?q?=20=E6=97=A0=E6=95=88=E7=9A=84=20bug=EF=BC=9B=20-=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20IAop.ConfigEntity=20=E9=85=8D=E7=BD=AE=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E7=89=B9=E6=80=A7=EF=BC=8C=E5=8F=AF=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=85=B6=E4=BB=96=20ORM=20=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E7=89=B9=E6=80=A7=EF=BC=8C#36=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataAnnotations/MySqlFluentTest.cs | 27 +++++- FreeSql.Tests/FreeSql.Tests.csproj | 3 +- .../SqlServer/Curd/SqlServerSelectTest.cs | 2 +- FreeSql.Tests/UnitTest1.cs | 17 +++- FreeSql/DataAnnotations/TableAttribute.cs | 6 -- FreeSql/FreeSql.csproj | 2 +- FreeSql/Interface/IAop.cs | 48 ++++++++++- .../Internal/CommonProvider/AopProvider.cs | 2 + .../SelectProvider/Select0Provider.cs | 8 +- FreeSql/Internal/CommonUtils.cs | 85 ++++++++++++++----- 10 files changed, 164 insertions(+), 36 deletions(-) diff --git a/FreeSql.Tests/DataAnnotations/MySqlFluentTest.cs b/FreeSql.Tests/DataAnnotations/MySqlFluentTest.cs index c8cde155..d373da3f 100644 --- a/FreeSql.Tests/DataAnnotations/MySqlFluentTest.cs +++ b/FreeSql.Tests/DataAnnotations/MySqlFluentTest.cs @@ -1,6 +1,6 @@ using FreeSql.DataAnnotations; -using FreeSql.Tests.DataContext.SqlServer; using System; +using System.Linq; using Xunit; namespace FreeSql.Tests.DataAnnotations { @@ -9,6 +9,31 @@ namespace FreeSql.Tests.DataAnnotations { public MySqlFluentTest() { } + [Fact] + public void AopConfigEntity() { + g.mysql.CodeFirst.ConfigEntity(a => a.Property(b => b.pkid).IsPrimary(true)); + + g.mysql.Aop.ConfigEntity = (s, e) => { + var attr = e.EntityType.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.Schema.TableAttribute), false).FirstOrDefault() as System.ComponentModel.DataAnnotations.Schema.TableAttribute; + if (attr != null) { + e.ModifyResult.Name = attr.Name; + } + }; + g.mysql.Aop.ConfigEntityProperty = (s, e) => { + if (e.Property.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false).Any()) { + e.ModifyResult.IsPrimary = true; + } + }; + + var tsql1 = g.mysql.Select().WhereDynamic(1).ToSql(); + } + [System.ComponentModel.DataAnnotations.Schema.Table("xxx")] + class ModelAopConfigEntity { + [System.ComponentModel.DataAnnotations.Key] + [Column(IsPrimary = false)] + public int pkid { get; set; } + } + [Fact] public void Fluent() { g.mysql.CodeFirst diff --git a/FreeSql.Tests/FreeSql.Tests.csproj b/FreeSql.Tests/FreeSql.Tests.csproj index da5a926d..28498764 100644 --- a/FreeSql.Tests/FreeSql.Tests.csproj +++ b/FreeSql.Tests/FreeSql.Tests.csproj @@ -7,10 +7,11 @@ + - + diff --git a/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index 356def11..c9e54380 100644 --- a/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -677,7 +677,7 @@ namespace FreeSql.Tests.SqlServer { [Fact] public void AsTable() { - var listt = select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList(); + var listt = select.AsTable((a, b) => "(select * from tb_topic22 where clicks > 10)").Page(1, 10).ToList(); Func tableRule = (type, oldname) => { if (type == typeof(Topic)) return oldname + "AsTable1"; diff --git a/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/UnitTest1.cs index 80f8b407..a2c5b50e 100644 --- a/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/UnitTest1.cs @@ -153,8 +153,23 @@ namespace FreeSql.Tests { ); + var neworder = new Order { + CustomerName = "testCustomer", + OrderTitle = "xxx#cccksksk", + TransactionDate = DateTime.Now, + OrderDetails = new List(new[] { + new OrderDetail { - var order = g.mysql.Select().Where(a => a.Id == 1).ToOne(); //查询订单表 + }, + new OrderDetail { + + } + }) + }; + + g.mysql.GetRepository().Insert(neworder); + + var order = g.mysql.Select().Where(a => a.Id == neworder.Id).ToOne(); //查询订单表 if (order == null) { var orderId = g.mysql.Insert(new Order { }).ExecuteIdentity(); order = g.mysql.Select(orderId).ToOne(); diff --git a/FreeSql/DataAnnotations/TableAttribute.cs b/FreeSql/DataAnnotations/TableAttribute.cs index b8266037..fe6788a5 100644 --- a/FreeSql/DataAnnotations/TableAttribute.cs +++ b/FreeSql/DataAnnotations/TableAttribute.cs @@ -16,12 +16,6 @@ namespace FreeSql.DataAnnotations { /// 查询过滤SQL,实现类似 a.IsDeleted = 1 功能 /// public string SelectFilter { get; set; } - - internal bool? _RowVersion; - /// - /// 修改/删除时,启用行版本检查 - /// - public bool RowVersion { get => _RowVersion ?? false; set => _RowVersion = value; } internal ConcurrentDictionary _columns { get; } = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); } diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index 8c1e2b9f..eb1f25ac 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 0.5.3 + 0.5.4 true YeXiangQin FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite. diff --git a/FreeSql/Interface/IAop.cs b/FreeSql/Interface/IAop.cs index 06fbc895..9559bc61 100644 --- a/FreeSql/Interface/IAop.cs +++ b/FreeSql/Interface/IAop.cs @@ -1,7 +1,9 @@ -using FreeSql.DatabaseModel; +using FreeSql.DataAnnotations; +using FreeSql.DatabaseModel; using System; using System.Collections.Generic; using System.Linq.Expressions; +using System.Reflection; namespace FreeSql { public interface IAop { @@ -20,6 +22,15 @@ namespace FreeSql { /// 可自定义解析表达式 /// EventHandler ParseExpression { get; set; } + + /// + /// 自定义实体的配置,方便和多个 ORM 共同使用 + /// + EventHandler ConfigEntity { get; set; } + /// + /// 自定义实体的属性配置,方便和多个 ORM 共同使用 + /// + EventHandler ConfigEntityProperty { get; set; } } public class AopToListEventArgs : EventArgs { @@ -61,4 +72,39 @@ namespace FreeSql { /// public string Result { get; set; } } + public class AopConfigEntityEventArgs : EventArgs { + public AopConfigEntityEventArgs(Type entityType) { + this.EntityType = entityType; + this.ModifyResult = new TableAttribute(); + } + + /// + /// 实体类型 + /// + public Type EntityType { get; } + /// + /// 实体配置 + /// + public TableAttribute ModifyResult { get; } + } + public class AopConfigEntityPropertyEventArgs : EventArgs { + public AopConfigEntityPropertyEventArgs(Type entityType, PropertyInfo property) { + this.EntityType = entityType; + this.Property = property; + this.ModifyResult = new ColumnAttribute(); + } + + /// + /// 实体类型 + /// + public Type EntityType { get; } + /// + /// 实体的属性 + /// + public PropertyInfo Property { get; } + /// + /// 实体的属性配置 + /// + public ColumnAttribute ModifyResult { get; } + } } diff --git a/FreeSql/Internal/CommonProvider/AopProvider.cs b/FreeSql/Internal/CommonProvider/AopProvider.cs index c7375c21..d8f856a2 100644 --- a/FreeSql/Internal/CommonProvider/AopProvider.cs +++ b/FreeSql/Internal/CommonProvider/AopProvider.cs @@ -9,5 +9,7 @@ namespace FreeSql.Internal.CommonProvider { public EventHandler ToList { get; set; } public EventHandler Where { get; set; } public EventHandler ParseExpression { get; set; } + public EventHandler ConfigEntity { get; set; } + public EventHandler ConfigEntityProperty { get; set; } } } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 5295afda..cd9753e9 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -288,8 +288,10 @@ namespace FreeSql.Internal.CommonProvider { return ret; }); } - public List ToList(bool includeNestedMembers = false) => this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevel2()); - public Task> ToListAsync(bool includeNestedMembers = false) => this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevel2()); + public List ToList(bool includeNestedMembers = false) => + this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll()); + public Task> ToListAsync(bool includeNestedMembers = false) => + this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll()); public T1 ToOne() { this.Limit(1); return this.ToList().FirstOrDefault(); @@ -350,7 +352,7 @@ namespace FreeSql.Internal.CommonProvider { public Func Read { get; set; } } protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevelAll() { - return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Alias}-{a.Type}")), s => { + return _dicGetAllFieldExpressionTree.GetOrAdd($"*{string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Alias}-{a.Type}"))}", s => { var type = _tables.First().Table.TypeLazy ?? _tables.First().Table.Type; var ormExp = Expression.Parameter(typeof(IFreeSql), "orm"); var rowExp = Expression.Parameter(typeof(DbDataReader), "row"); diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index 7fccbcd2..fa35f967 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -58,31 +58,74 @@ namespace FreeSql.Internal { return dicConfigEntity.TryGetValue(type, out var trytb) ? trytb : null; } internal TableAttribute GetEntityTableAttribute(Type type) { - var attr = type.GetCustomAttributes(typeof(TableAttribute), false).LastOrDefault() as TableAttribute; - if (dicConfigEntity.TryGetValue(type, out var trytb) == false) return attr; + TableAttribute attr = null; + if (_orm.Aop.ConfigEntity != null) { + var aope = new AopConfigEntityEventArgs(type); + _orm.Aop.ConfigEntity(_orm, aope); + attr = aope.ModifyResult; + } if (attr == null) attr = new TableAttribute(); - - if (string.IsNullOrEmpty(attr.Name)) attr.Name = trytb.Name; - if (string.IsNullOrEmpty(attr.OldName)) attr.OldName = trytb.OldName; - if (string.IsNullOrEmpty(attr.SelectFilter)) attr.SelectFilter = trytb.SelectFilter; - return attr; + if (dicConfigEntity.TryGetValue(type, out var trytb)) { + if (!string.IsNullOrEmpty(trytb.Name)) attr.Name = trytb.Name; + if (!string.IsNullOrEmpty(trytb.OldName)) attr.OldName = trytb.OldName; + if (!string.IsNullOrEmpty(trytb.SelectFilter)) attr.SelectFilter = trytb.SelectFilter; + } + var attrs = type.GetCustomAttributes(typeof(TableAttribute), false); + foreach (var tryattrobj in attrs) { + var tryattr = tryattrobj as TableAttribute; + if (tryattr == null) continue; + if (!string.IsNullOrEmpty(tryattr.Name)) attr.Name = tryattr.Name; + if (!string.IsNullOrEmpty(tryattr.OldName)) attr.OldName = tryattr.OldName; + if (!string.IsNullOrEmpty(tryattr.SelectFilter)) attr.SelectFilter = tryattr.SelectFilter; + } + if (!string.IsNullOrEmpty(attr.Name)) return attr; + if (!string.IsNullOrEmpty(attr.OldName)) return attr; + if (!string.IsNullOrEmpty(attr.SelectFilter)) return attr; + return null; } internal ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) { - var attr = proto.GetCustomAttributes(typeof(ColumnAttribute), false).LastOrDefault() as ColumnAttribute; - if (dicConfigEntity.TryGetValue(type, out var trytb) == false) return attr; - if (trytb._columns.TryGetValue(proto.Name, out var trycol) == false) return attr; + ColumnAttribute attr = null; + if (_orm.Aop.ConfigEntityProperty != null) { + var aope = new AopConfigEntityPropertyEventArgs(type, proto); + _orm.Aop.ConfigEntityProperty(_orm, aope); + attr = aope.ModifyResult; + } if (attr == null) attr = new ColumnAttribute(); - - if (string.IsNullOrEmpty(attr.Name)) attr.Name = trycol.Name; - if (string.IsNullOrEmpty(attr.OldName)) attr.OldName = trycol.OldName; - if (string.IsNullOrEmpty(attr.DbType)) attr.DbType = trycol.DbType; - if (attr._IsPrimary == null) attr._IsPrimary = trycol.IsPrimary; - if (attr._IsIdentity == null) attr._IsIdentity = trycol.IsIdentity; - if (attr._IsNullable == null) attr._IsNullable = trycol.IsNullable; - if (attr._IsIgnore == null) attr._IsIgnore = trycol.IsIgnore; - if (attr._IsVersion == null) attr._IsVersion = trycol.IsVersion; - if (attr.DbDefautValue == null) attr.DbDefautValue = trycol.DbDefautValue; - return attr; + if (dicConfigEntity.TryGetValue(type, out var trytb) && trytb._columns.TryGetValue(proto.Name, out var trycol)) { + if (!string.IsNullOrEmpty(trycol.Name)) attr.Name = trycol.Name; + if (!string.IsNullOrEmpty(trycol.OldName)) attr.OldName = trycol.OldName; + if (!string.IsNullOrEmpty(trycol.DbType)) attr.DbType = trycol.DbType; + if (trycol._IsPrimary != null) attr._IsPrimary = trycol.IsPrimary; + if (trycol._IsIdentity != null) attr._IsIdentity = trycol.IsIdentity; + if (trycol._IsNullable != null) attr._IsNullable = trycol.IsNullable; + if (trycol._IsIgnore != null) attr._IsIgnore = trycol.IsIgnore; + if (trycol._IsVersion != null) attr._IsVersion = trycol.IsVersion; + if (trycol.DbDefautValue != null) attr.DbDefautValue = trycol.DbDefautValue; + } + var attrs = proto.GetCustomAttributes(typeof(ColumnAttribute), false); + foreach (var tryattrobj in attrs) { + var tryattr = tryattrobj as ColumnAttribute; + if (tryattr == null) continue; + if (!string.IsNullOrEmpty(tryattr.Name)) attr.Name = tryattr.Name; + if (!string.IsNullOrEmpty(tryattr.OldName)) attr.OldName = tryattr.OldName; + if (!string.IsNullOrEmpty(tryattr.DbType)) attr.DbType = tryattr.DbType; + if (tryattr._IsPrimary != null) attr._IsPrimary = tryattr.IsPrimary; + if (tryattr._IsIdentity != null) attr._IsIdentity = tryattr.IsIdentity; + if (tryattr._IsNullable != null) attr._IsNullable = tryattr.IsNullable; + if (tryattr._IsIgnore != null) attr._IsIgnore = tryattr.IsIgnore; + if (tryattr._IsVersion != null) attr._IsVersion = tryattr.IsVersion; + if (tryattr.DbDefautValue != null) attr.DbDefautValue = tryattr.DbDefautValue; + } + if (!string.IsNullOrEmpty(attr.Name)) return attr; + if (!string.IsNullOrEmpty(attr.OldName)) return attr; + if (!string.IsNullOrEmpty(attr.DbType)) return attr; + if (attr._IsPrimary != null) return attr; + if (attr._IsIdentity != null) return attr; + if (attr._IsNullable != null) return attr; + if (attr._IsIgnore != null) return attr; + if (attr._IsVersion != null) return attr; + if (attr.DbDefautValue != null) return attr; + return null; } internal string WhereObject(TableInfo table, string aliasAndDot, object dywhere) {