From 73c87513d2ed69dd7698c3d6a10fdb1806679a07 Mon Sep 17 00:00:00 2001
From: 28810 <28810@YEXIANGQIN>
Date: Fri, 31 Jul 2020 03:07:13 +0800
Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20ColumnAttribute=20Prec?=
=?UTF-8?q?ision/Scale=20=E8=AE=BE=E7=BD=AE=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../EfCoreFluentApi/EfCoreColumnFluent.cs | 6 +
FreeSql.DbContext/FreeSql.DbContext.xml | 9 -
FreeSql/DataAnnotations/ColumnAttribute.cs | 11 +
FreeSql/DataAnnotations/ColumnFluent.cs | 13 +
FreeSql/FreeSql.xml | 328 ++++++++++--------
FreeSql/Internal/CommonExpression.cs | 8 +-
FreeSql/Internal/CommonUtils.cs | 6 +-
FreeSql/Internal/UtilsExpressionTree.cs | 15 +-
.../SqlServer/OdbcSqlServerExpression.cs | 2 +-
9 files changed, 235 insertions(+), 163 deletions(-)
diff --git a/FreeSql.DbContext/EfCoreFluentApi/EfCoreColumnFluent.cs b/FreeSql.DbContext/EfCoreFluentApi/EfCoreColumnFluent.cs
index 0b87862c..1f89fc59 100644
--- a/FreeSql.DbContext/EfCoreFluentApi/EfCoreColumnFluent.cs
+++ b/FreeSql.DbContext/EfCoreFluentApi/EfCoreColumnFluent.cs
@@ -54,5 +54,11 @@ namespace FreeSql.Extensions.EfCoreFluentApi
//{
// return this;
//}
+ public EfCoreColumnFluent HasPrecision(int precision, int scale = 0)
+ {
+ _cf.Precision(precision, scale);
+ return this;
+ }
+
}
}
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 4854f49c..474ea8d5 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -486,14 +486,5 @@
-
-
- 批量注入 Repository,可以参考代码自行调整
-
-
-
-
-
-
diff --git a/FreeSql/DataAnnotations/ColumnAttribute.cs b/FreeSql/DataAnnotations/ColumnAttribute.cs
index b6b11569..4dd251ed 100644
--- a/FreeSql/DataAnnotations/ColumnAttribute.cs
+++ b/FreeSql/DataAnnotations/ColumnAttribute.cs
@@ -104,5 +104,16 @@ namespace FreeSql.DataAnnotations
/// 注意:如果是 getdate() 这种请可考虑使用 ServerTime,因为它对数据库间作了适配
///
public string InsertValueSql { get; set; }
+
+ internal int? _Precision;
+ ///
+ /// decimal/numeric 类型的长度
+ ///
+ public int Precision { get => _Precision ?? 0; set => _Precision = value; }
+ internal int? _Scale;
+ ///
+ /// decimal/numeric 类型的小数位长度
+ ///
+ public int Scale { get => _Scale ?? 0; set => _Scale = value; }
}
}
diff --git a/FreeSql/DataAnnotations/ColumnFluent.cs b/FreeSql/DataAnnotations/ColumnFluent.cs
index 4a1adc93..4b5b1e09 100644
--- a/FreeSql/DataAnnotations/ColumnFluent.cs
+++ b/FreeSql/DataAnnotations/ColumnFluent.cs
@@ -176,5 +176,18 @@ namespace FreeSql.DataAnnotations
_column.InsertValueSql = value;
return this;
}
+
+ ///
+ /// decimal/numeric 类型的长度/小数位长度
+ ///
+ /// 总长度
+ /// 小数位长度
+ ///
+ public ColumnFluent Precision(int precision, int scale = 0)
+ {
+ _column.Precision = precision;
+ _column.Scale = scale;
+ return this;
+ }
}
}
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 78dd9783..7feb5fa9 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -105,6 +105,16 @@
注意:如果是 getdate() 这种请可考虑使用 ServerTime,因为它对数据库间作了适配
+
+
+ decimal/numeric 类型的长度
+
+
+
+
+ decimal/numeric 类型的小数位长度
+
+
数据库列名
@@ -213,6 +223,14 @@
+
+
+ decimal/numeric 类型的长度/小数位长度
+
+ 总长度
+ 小数位长度
+
+
自定义表达式函数解析
@@ -2546,137 +2564,6 @@
-
-
- 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
-
-
-
-
-
-
-
-
- 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > ?age", new { age = 25 })
-
-
-
-
-
-
- 查询
-
-
-
-
-
-
- 查询,ExecuteArrayAsync("select * from user where age > ?age", new { age = 25 })
-
-
-
-
-
-
-
- 查询
-
-
-
-
-
-
- 查询,ExecuteDataSetAsync("select * from user where age > ?age; select 2", new { age = 25 })
-
-
-
-
-
-
-
- 查询
-
-
-
-
-
-
- 查询,ExecuteDataTableAsync("select * from user where age > ?age", new { age = 25 })
-
-
-
-
-
-
-
- 在【主库】执行
-
-
-
-
-
-
-
- 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > ?age", new { age = 25 })
-
-
-
-
-
-
-
- 在【主库】执行
-
-
-
-
-
-
-
- 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > ?age", new { age = 25 })
-
-
-
-
-
-
-
- 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new SqlParameter { ParameterName = "age", Value = 25 })
-
-
-
-
-
-
-
-
-
- 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new { age = 25 })
-
-
-
-
-
-
-
-
- 执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
-
-
-
-
-
-
-
-
-
- 执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new { age = 25 })
-
-
-
-
-
-
可自定义解析表达式
@@ -3346,12 +3233,6 @@
超时
-
-
- 获取资源
-
-
-
使用完毕后,归还资源
@@ -3422,12 +3303,6 @@
资源对象
-
-
- 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
-
- 资源对象
-
归还对象给对象池的时候触发
@@ -4085,4 +3960,171 @@
+
+
+
+
+ 使用 or 拼接两个 lambda 表达式
+
+
+ true 时生效
+
+
+
+
+
+ 将 lambda 表达式取反
+
+
+ true 时生效
+
+
+
+
+ 生成类似Mongodb的ObjectId有序、不重复Guid
+
+
+
+
+
+ 插入数据
+
+
+
+
+
+
+ 插入数据,传入实体
+
+
+
+
+
+
+
+ 插入数据,传入实体数组
+
+
+
+
+
+
+
+ 插入数据,传入实体集合
+
+
+
+
+
+
+
+ 插入数据,传入实体集合
+
+
+
+
+
+
+
+ 插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下:
+ MySql 5.6+: on duplicate key update
+ PostgreSQL 9.4+: on conflict do update
+ SqlServer 2008+: merge into
+ Oracle 11+: merge into
+ Sqlite: replace into
+ 达梦: merge into
+ 人大金仓:on conflict do update
+ 神通:merge into
+ MsAccess:不支持
+ 注意区别:FreeSql.Repository 仓储也有 InsertOrUpdate 方法(不依赖数据库特性)
+
+
+
+
+
+
+ 修改数据
+
+
+
+
+
+
+ 修改数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
+
+
+ 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合
+
+
+
+
+ 查询数据
+
+
+
+
+
+
+ 查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
+
+
+ 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合
+
+
+
+
+ 删除数据
+
+
+
+
+
+
+ 删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
+
+
+ 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合
+
+
+
+
+ 开启事务(不支持异步)
+ v1.5.0 关闭了线程事务超时自动提交的机制
+
+ 事务体 () => {}
+
+
+
+ 开启事务(不支持异步)
+ v1.5.0 关闭了线程事务超时自动提交的机制
+
+
+ 事务体 () => {}
+
+
+
+ 数据库访问对象
+
+
+
+
+ 所有拦截方法都在这里
+
+
+
+
+ CodeFirst 模式开发相关方法
+
+
+
+
+ DbFirst 模式开发相关方法
+
+
+
+
+ 全局过滤设置,可默认附加为 Select/Update/Delete 条件
+
+
+
diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs
index 5f6fb7ea..1050d677 100644
--- a/FreeSql/Internal/CommonExpression.cs
+++ b/FreeSql/Internal/CommonExpression.cs
@@ -41,7 +41,7 @@ namespace FreeSql.Internal
field.Append(", ").Append(parent.DbField);
if (index >= 0) field.Append(_common.FieldAsAlias($"as{++index}"));
else if (index == ReadAnonymousFieldAsCsName && string.IsNullOrEmpty(parent.CsName) == false) field.Append(_common.FieldAsAlias(parent.CsName));
- if (parent.CsType == null) parent.CsType = exp.Type;
+ if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap);
case ExpressionType.Constant:
@@ -61,7 +61,7 @@ namespace FreeSql.Internal
field.Append(", ").Append(parent.DbField);
if (index >= 0) field.Append(_common.FieldAsAlias($"as{++index}"));
else if (index == ReadAnonymousFieldAsCsName && string.IsNullOrEmpty(parent.CsName) == false) field.Append(_common.FieldAsAlias(parent.CsName));
- if (parent.CsType == null) parent.CsType = exp.Type;
+ if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
case ExpressionType.Call:
var callExp = exp as MethodCallExpression;
@@ -79,7 +79,7 @@ namespace FreeSql.Internal
field.Append(", ").Append(parent.DbField);
if (index >= 0) field.Append(_common.FieldAsAlias($"as{++index}"));
else if (index == ReadAnonymousFieldAsCsName && string.IsNullOrEmpty(parent.CsName) == false) field.Append(_common.FieldAsAlias(parent.CsName));
- if (parent.CsType == null) parent.CsType = exp.Type;
+ if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
case ExpressionType.Parameter:
case ExpressionType.MemberAccess:
@@ -265,7 +265,7 @@ namespace FreeSql.Internal
field.Append(", ").Append(parent.DbField);
if (index >= 0) field.Append(_common.FieldAsAlias($"as{++index}"));
else if (index == ReadAnonymousFieldAsCsName && string.IsNullOrEmpty(parent.CsName) == false) field.Append(_common.FieldAsAlias(parent.CsName));
- if (parent.CsType == null) parent.CsType = exp.Type;
+ if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
}
public object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead, ReadAnonymousDbValueRef dbValue)
diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs
index ef10b55a..922d1573 100644
--- a/FreeSql/Internal/CommonUtils.cs
+++ b/FreeSql/Internal/CommonUtils.cs
@@ -154,6 +154,8 @@ namespace FreeSql.Internal
if (trycol.ServerTime != DateTimeKind.Unspecified) attr.ServerTime = trycol.ServerTime;
if (trycol._StringLength != null) attr.StringLength = trycol.StringLength;
if (!string.IsNullOrEmpty(trycol.InsertValueSql)) attr.InsertValueSql = trycol.InsertValueSql;
+ if (trycol._Precision != null) attr.Precision = trycol.Precision;
+ if (trycol._Scale != null) attr.Scale = trycol.Scale;
}
var attrs = proto.GetCustomAttributes(typeof(ColumnAttribute), false);
foreach (var tryattrobj in attrs)
@@ -174,7 +176,9 @@ namespace FreeSql.Internal
if (tryattr._CanUpdate != null) attr._CanUpdate = tryattr.CanUpdate;
if (tryattr.ServerTime != DateTimeKind.Unspecified) attr.ServerTime = tryattr.ServerTime;
if (tryattr._StringLength != null) attr.StringLength = tryattr.StringLength;
- if (!string.IsNullOrEmpty(tryattr.InsertValueSql)) attr.InsertValueSql = tryattr.InsertValueSql;
+ if (!string.IsNullOrEmpty(tryattr.InsertValueSql)) attr.InsertValueSql = tryattr.InsertValueSql;
+ if (tryattr._Precision != null) attr.Precision = tryattr.Precision;
+ if (tryattr._Scale != null) attr.Scale = tryattr.Scale;
}
ColumnAttribute ret = null;
if (!string.IsNullOrEmpty(attr.Name)) ret = attr;
diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs
index a499e1ff..98d6edeb 100644
--- a/FreeSql/Internal/UtilsExpressionTree.cs
+++ b/FreeSql/Internal/UtilsExpressionTree.cs
@@ -279,19 +279,19 @@ namespace FreeSql.Internal
if (colattr.MapType == typeof(byte[]) && colattr.StringLength != 0)
{
int strlen = colattr.StringLength;
- var charPatten = @"(VARBINARY|BINARY|BYTEA)\s*(\([^\)]*\))?";
+ var bytePatten = @"(VARBINARY|BINARY|BYTEA)\s*(\([^\)]*\))?";
switch (common._orm.Ado.DataType)
{
case DataType.MySql:
case DataType.OdbcMySql:
if (strlen == -2) colattr.DbType = "LONGBLOB";
else if (strlen < 0) colattr.DbType = "BLOB";
- else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
+ else colattr.DbType = Regex.Replace(colattr.DbType, bytePatten, $"$1({strlen})");
break;
case DataType.SqlServer:
case DataType.OdbcSqlServer:
- if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1(MAX)");
- else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
+ if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, bytePatten, $"$1(MAX)");
+ else colattr.DbType = Regex.Replace(colattr.DbType, bytePatten, $"$1({strlen})");
break;
case DataType.PostgreSQL:
case DataType.OdbcPostgreSQL:
@@ -314,10 +314,15 @@ namespace FreeSql.Internal
break;
case DataType.MsAccess:
if (strlen < 0) colattr.DbType = "BLOB";
- else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
+ else colattr.DbType = Regex.Replace(colattr.DbType, bytePatten, $"$1({strlen})");
break;
}
}
+ if (colattr.MapType == typeof(decimal) && colattr.Precision > 0)
+ {
+ var decimalPatten = @"(DECIMAL|NUMERIC|NUMBER)\s*(\([^\)]*\))?";
+ colattr.DbType = Regex.Replace(colattr.DbType, decimalPatten, $"$1({colattr.Precision},{colattr.Scale})");
+ }
if (trytb.Columns.ContainsKey(colattr.Name)) throw new Exception($"ColumnAttribute.Name {colattr.Name} 重复存在,请检查(注意:不区分大小写)");
if (trytb.ColumnsByCs.ContainsKey(p.Name)) throw new Exception($"属性名 {p.Name} 重复存在,请检查(注意:不区分大小写)");
diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs
index ed2ef297..76f2ae6d 100644
--- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs
+++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs
@@ -113,7 +113,7 @@ namespace FreeSql.Odbc.SqlServer
{
case "First":
case "FirstOrDefault":
- return $"substr({getExp(callExp.Arguments[0])}, 1, 1)";
+ return $"substring({getExp(callExp.Arguments[0])}, 1, 1)";
}
}
}