- 修复 ISelect.ToList(true) 无效的 bug;

- 增加 IAop.ConfigEntity 配置实体特性,可实现使用其他 ORM 的实体特性,#36;
This commit is contained in:
28810 2019-04-24 15:09:32 +08:00
parent b16218d779
commit e2d33e943f
10 changed files with 164 additions and 36 deletions

View File

@ -1,6 +1,6 @@
using FreeSql.DataAnnotations; using FreeSql.DataAnnotations;
using FreeSql.Tests.DataContext.SqlServer;
using System; using System;
using System.Linq;
using Xunit; using Xunit;
namespace FreeSql.Tests.DataAnnotations { namespace FreeSql.Tests.DataAnnotations {
@ -9,6 +9,31 @@ namespace FreeSql.Tests.DataAnnotations {
public MySqlFluentTest() { public MySqlFluentTest() {
} }
[Fact]
public void AopConfigEntity() {
g.mysql.CodeFirst.ConfigEntity<ModelAopConfigEntity>(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<ModelAopConfigEntity>().WhereDynamic(1).ToSql();
}
[System.ComponentModel.DataAnnotations.Schema.Table("xxx")]
class ModelAopConfigEntity {
[System.ComponentModel.DataAnnotations.Key]
[Column(IsPrimary = false)]
public int pkid { get; set; }
}
[Fact] [Fact]
public void Fluent() { public void Fluent() {
g.mysql.CodeFirst g.mysql.CodeFirst

View File

@ -7,10 +7,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="FreeSql.DbContext" Version="0.5.3" /> <PackageReference Include="FreeSql.DbContext" Version="0.5.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -677,7 +677,7 @@ namespace FreeSql.Tests.SqlServer {
[Fact] [Fact]
public void AsTable() { 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<Type, string, string> tableRule = (type, oldname) => { Func<Type, string, string> tableRule = (type, oldname) => {
if (type == typeof(Topic)) return oldname + "AsTable1"; if (type == typeof(Topic)) return oldname + "AsTable1";

View File

@ -153,8 +153,23 @@ namespace FreeSql.Tests {
); );
var neworder = new Order {
CustomerName = "testCustomer",
OrderTitle = "xxx#cccksksk",
TransactionDate = DateTime.Now,
OrderDetails = new List<OrderDetail>(new[] {
new OrderDetail {
var order = g.mysql.Select<Order>().Where(a => a.Id == 1).ToOne(); //查询订单表 },
new OrderDetail {
}
})
};
g.mysql.GetRepository<Order>().Insert(neworder);
var order = g.mysql.Select<Order>().Where(a => a.Id == neworder.Id).ToOne(); //查询订单表
if (order == null) { if (order == null) {
var orderId = g.mysql.Insert(new Order { }).ExecuteIdentity(); var orderId = g.mysql.Insert(new Order { }).ExecuteIdentity();
order = g.mysql.Select<Order>(orderId).ToOne(); order = g.mysql.Select<Order>(orderId).ToOne();

View File

@ -16,12 +16,6 @@ namespace FreeSql.DataAnnotations {
/// 查询过滤SQL实现类似 a.IsDeleted = 1 功能 /// 查询过滤SQL实现类似 a.IsDeleted = 1 功能
/// </summary> /// </summary>
public string SelectFilter { get; set; } public string SelectFilter { get; set; }
internal bool? _RowVersion;
/// <summary>
/// 修改/删除时,启用行版本检查
/// </summary>
public bool RowVersion { get => _RowVersion ?? false; set => _RowVersion = value; }
internal ConcurrentDictionary<string, ColumnAttribute> _columns { get; } = new ConcurrentDictionary<string, ColumnAttribute>(StringComparer.CurrentCultureIgnoreCase); internal ConcurrentDictionary<string, ColumnAttribute> _columns { get; } = new ConcurrentDictionary<string, ColumnAttribute>(StringComparer.CurrentCultureIgnoreCase);
} }

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<Version>0.5.3</Version> <Version>0.5.4</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>YeXiangQin</Authors> <Authors>YeXiangQin</Authors>
<Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description> <Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description>

View File

@ -1,7 +1,9 @@
using FreeSql.DatabaseModel; using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection;
namespace FreeSql { namespace FreeSql {
public interface IAop { public interface IAop {
@ -20,6 +22,15 @@ namespace FreeSql {
/// 可自定义解析表达式 /// 可自定义解析表达式
/// </summary> /// </summary>
EventHandler<AopParseExpressionEventArgs> ParseExpression { get; set; } EventHandler<AopParseExpressionEventArgs> ParseExpression { get; set; }
/// <summary>
/// 自定义实体的配置,方便和多个 ORM 共同使用
/// </summary>
EventHandler<AopConfigEntityEventArgs> ConfigEntity { get; set; }
/// <summary>
/// 自定义实体的属性配置,方便和多个 ORM 共同使用
/// </summary>
EventHandler<AopConfigEntityPropertyEventArgs> ConfigEntityProperty { get; set; }
} }
public class AopToListEventArgs : EventArgs { public class AopToListEventArgs : EventArgs {
@ -61,4 +72,39 @@ namespace FreeSql {
/// </summary> /// </summary>
public string Result { get; set; } public string Result { get; set; }
} }
public class AopConfigEntityEventArgs : EventArgs {
public AopConfigEntityEventArgs(Type entityType) {
this.EntityType = entityType;
this.ModifyResult = new TableAttribute();
}
/// <summary>
/// 实体类型
/// </summary>
public Type EntityType { get; }
/// <summary>
/// 实体配置
/// </summary>
public TableAttribute ModifyResult { get; }
}
public class AopConfigEntityPropertyEventArgs : EventArgs {
public AopConfigEntityPropertyEventArgs(Type entityType, PropertyInfo property) {
this.EntityType = entityType;
this.Property = property;
this.ModifyResult = new ColumnAttribute();
}
/// <summary>
/// 实体类型
/// </summary>
public Type EntityType { get; }
/// <summary>
/// 实体的属性
/// </summary>
public PropertyInfo Property { get; }
/// <summary>
/// 实体的属性配置
/// </summary>
public ColumnAttribute ModifyResult { get; }
}
} }

View File

@ -9,5 +9,7 @@ namespace FreeSql.Internal.CommonProvider {
public EventHandler<AopToListEventArgs> ToList { get; set; } public EventHandler<AopToListEventArgs> ToList { get; set; }
public EventHandler<AopWhereEventArgs> Where { get; set; } public EventHandler<AopWhereEventArgs> Where { get; set; }
public EventHandler<AopParseExpressionEventArgs> ParseExpression { get; set; } public EventHandler<AopParseExpressionEventArgs> ParseExpression { get; set; }
public EventHandler<AopConfigEntityEventArgs> ConfigEntity { get; set; }
public EventHandler<AopConfigEntityPropertyEventArgs> ConfigEntityProperty { get; set; }
} }
} }

View File

@ -288,8 +288,10 @@ namespace FreeSql.Internal.CommonProvider {
return ret; return ret;
}); });
} }
public List<T1> ToList(bool includeNestedMembers = false) => this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevel2()); public List<T1> ToList(bool includeNestedMembers = false) =>
public Task<List<T1>> ToListAsync(bool includeNestedMembers = false) => this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevel2()); this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
public Task<List<T1>> ToListAsync(bool includeNestedMembers = false) =>
this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
public T1 ToOne() { public T1 ToOne() {
this.Limit(1); this.Limit(1);
return this.ToList().FirstOrDefault(); return this.ToList().FirstOrDefault();
@ -350,7 +352,7 @@ namespace FreeSql.Internal.CommonProvider {
public Func<IFreeSql, DbDataReader, T1> Read { get; set; } public Func<IFreeSql, DbDataReader, T1> Read { get; set; }
} }
protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevelAll() { 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 type = _tables.First().Table.TypeLazy ?? _tables.First().Table.Type;
var ormExp = Expression.Parameter(typeof(IFreeSql), "orm"); var ormExp = Expression.Parameter(typeof(IFreeSql), "orm");
var rowExp = Expression.Parameter(typeof(DbDataReader), "row"); var rowExp = Expression.Parameter(typeof(DbDataReader), "row");

View File

@ -58,31 +58,74 @@ namespace FreeSql.Internal {
return dicConfigEntity.TryGetValue(type, out var trytb) ? trytb : null; return dicConfigEntity.TryGetValue(type, out var trytb) ? trytb : null;
} }
internal TableAttribute GetEntityTableAttribute(Type type) { internal TableAttribute GetEntityTableAttribute(Type type) {
var attr = type.GetCustomAttributes(typeof(TableAttribute), false).LastOrDefault() as TableAttribute; TableAttribute attr = null;
if (dicConfigEntity.TryGetValue(type, out var trytb) == false) return attr; 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 (attr == null) attr = new TableAttribute();
if (dicConfigEntity.TryGetValue(type, out var trytb)) {
if (string.IsNullOrEmpty(attr.Name)) attr.Name = trytb.Name; if (!string.IsNullOrEmpty(trytb.Name)) attr.Name = trytb.Name;
if (string.IsNullOrEmpty(attr.OldName)) attr.OldName = trytb.OldName; if (!string.IsNullOrEmpty(trytb.OldName)) attr.OldName = trytb.OldName;
if (string.IsNullOrEmpty(attr.SelectFilter)) attr.SelectFilter = trytb.SelectFilter; if (!string.IsNullOrEmpty(trytb.SelectFilter)) attr.SelectFilter = trytb.SelectFilter;
return attr; }
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) { internal ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) {
var attr = proto.GetCustomAttributes(typeof(ColumnAttribute), false).LastOrDefault() as ColumnAttribute; ColumnAttribute attr = null;
if (dicConfigEntity.TryGetValue(type, out var trytb) == false) return attr; if (_orm.Aop.ConfigEntityProperty != null) {
if (trytb._columns.TryGetValue(proto.Name, out var trycol) == false) return attr; var aope = new AopConfigEntityPropertyEventArgs(type, proto);
_orm.Aop.ConfigEntityProperty(_orm, aope);
attr = aope.ModifyResult;
}
if (attr == null) attr = new ColumnAttribute(); if (attr == null) attr = new ColumnAttribute();
if (dicConfigEntity.TryGetValue(type, out var trytb) && trytb._columns.TryGetValue(proto.Name, out var trycol)) {
if (string.IsNullOrEmpty(attr.Name)) attr.Name = trycol.Name; if (!string.IsNullOrEmpty(trycol.Name)) attr.Name = trycol.Name;
if (string.IsNullOrEmpty(attr.OldName)) attr.OldName = trycol.OldName; if (!string.IsNullOrEmpty(trycol.OldName)) attr.OldName = trycol.OldName;
if (string.IsNullOrEmpty(attr.DbType)) attr.DbType = trycol.DbType; if (!string.IsNullOrEmpty(trycol.DbType)) attr.DbType = trycol.DbType;
if (attr._IsPrimary == null) attr._IsPrimary = trycol.IsPrimary; if (trycol._IsPrimary != null) attr._IsPrimary = trycol.IsPrimary;
if (attr._IsIdentity == null) attr._IsIdentity = trycol.IsIdentity; if (trycol._IsIdentity != null) attr._IsIdentity = trycol.IsIdentity;
if (attr._IsNullable == null) attr._IsNullable = trycol.IsNullable; if (trycol._IsNullable != null) attr._IsNullable = trycol.IsNullable;
if (attr._IsIgnore == null) attr._IsIgnore = trycol.IsIgnore; if (trycol._IsIgnore != null) attr._IsIgnore = trycol.IsIgnore;
if (attr._IsVersion == null) attr._IsVersion = trycol.IsVersion; if (trycol._IsVersion != null) attr._IsVersion = trycol.IsVersion;
if (attr.DbDefautValue == null) attr.DbDefautValue = trycol.DbDefautValue; if (trycol.DbDefautValue != null) attr.DbDefautValue = trycol.DbDefautValue;
return attr; }
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) { internal string WhereObject(TableInfo table, string aliasAndDot, object dywhere) {