mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 20:38:16 +08:00
- 增加 实体特性 [Column(ServerTime = DateTimeKind.Utc)] 使用数据库时间执行插入数据;
- 修复 ToList(a => new Dto { .. }) 在使用 GroupBy 之后报错的 bug; - 修复 注释迁移到数据库,在 asp.net 4.7 无效的问题;
This commit is contained in:
@ -43,11 +43,6 @@ namespace FreeSql.DataAnnotations
|
||||
/// </summary>
|
||||
public bool IsVersion { get => _IsVersion ?? false; set => _IsVersion = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库默认值
|
||||
/// </summary>
|
||||
public object DbDefautValue { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型映射,除了可做基本的类型映射外,特别介绍的功能:<para></para>
|
||||
/// 1、将 enum 属性映射成 typeof(string)<para></para>
|
||||
@ -76,5 +71,18 @@ namespace FreeSql.DataAnnotations
|
||||
/// 该字段是否可以更新,默认值true,指定为false更新时该字段会被忽略
|
||||
/// </summary>
|
||||
public bool CanUpdate { get => _CanUpdate ?? true; set => _CanUpdate = value; }
|
||||
|
||||
internal DateTimeKind? _ServerTime;
|
||||
/// <summary>
|
||||
/// 标记属性为数据库服务器时间(utc/local),在插入的时候使用类似 getdate() 执行
|
||||
/// </summary>
|
||||
public DateTimeKind ServerTime
|
||||
{
|
||||
get => _ServerTime ?? DateTimeKind.Local;
|
||||
set
|
||||
{
|
||||
_ServerTime = value == DateTimeKind.Unspecified ? DateTimeKind.Local : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,5 +124,16 @@ namespace FreeSql.DataAnnotations
|
||||
_column.CanUpdate = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记属性为数据库服务器时间(utc/local),在插入的时候使用类似 getdate() 执行
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public ColumnFluent ServerTime(DateTimeKind value)
|
||||
{
|
||||
_column.ServerTime = value;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public static partial class FreeSqlGlobalExtensions
|
||||
});
|
||||
public static bool IsIntegerType(this Type that) => that == null ? false : (dicIsNumberType.Value.TryGetValue(that, out var tryval) ? tryval : false);
|
||||
public static bool IsNumberType(this Type that) => that == null ? false : dicIsNumberType.Value.ContainsKey(that);
|
||||
public static bool IsNullableType(this Type that) => that?.FullName.StartsWith("System.Nullable`1[") == true;
|
||||
public static bool IsNullableType(this Type that) => that.IsArray == false && that?.FullName.StartsWith("System.Nullable`1[") == true;
|
||||
public static bool IsAnonymousType(this Type that) => that?.FullName.StartsWith("<>f__AnonymousType") == true;
|
||||
public static bool IsArrayOrList(this Type that) => that == null ? false : (that.IsArray || typeof(IList).IsAssignableFrom(that));
|
||||
public static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GetGenericArguments().First() : that;
|
||||
|
@ -45,11 +45,6 @@
|
||||
设置行锁(乐观锁)版本号,每次更新累加版本号,若更新整个实体时会附带当前的版本号判断(修改失败时抛出异常)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.DataAnnotations.ColumnAttribute.DbDefautValue">
|
||||
<summary>
|
||||
数据库默认值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.DataAnnotations.ColumnAttribute.MapType">
|
||||
<summary>
|
||||
类型映射,除了可做基本的类型映射外,特别介绍的功能:<para></para>
|
||||
@ -78,6 +73,11 @@
|
||||
该字段是否可以更新,默认值true,指定为false更新时该字段会被忽略
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.DataAnnotations.ColumnAttribute.ServerTime">
|
||||
<summary>
|
||||
标记属性为数据库服务器时间(utc/local),在插入的时候使用类似 getdate() 执行
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSql.DataAnnotations.ColumnFluent.Name(System.String)">
|
||||
<summary>
|
||||
数据库列名
|
||||
@ -152,6 +152,13 @@
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.DataAnnotations.ColumnFluent.ServerTime(System.DateTimeKind)">
|
||||
<summary>
|
||||
标记属性为数据库服务器时间(utc/local),在插入的时候使用类似 getdate() 执行
|
||||
</summary>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:FreeSql.DataAnnotations.ExpressionCallAttribute">
|
||||
<summary>
|
||||
自定义表达式函数解析<para></para>
|
||||
|
@ -110,7 +110,7 @@ namespace FreeSql.Internal
|
||||
parent.Consturctor = initExp.NewExpression.Type.GetConstructors()[0];
|
||||
parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
|
||||
|
||||
if (initExp.NewExpression.Type != _tables.FirstOrDefault()?.Table.Type)
|
||||
if (_tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type)
|
||||
{
|
||||
//dto 映射
|
||||
var dtoProps = initExp.NewExpression.Type.GetPropertiesDictIgnoreCase().Values;
|
||||
|
@ -445,13 +445,18 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name)) continue;
|
||||
|
||||
if (colidx2 > 0) sb.Append(", ");
|
||||
object val = col.GetMapValue(d);
|
||||
if (_noneParameter)
|
||||
sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val));
|
||||
if (string.IsNullOrEmpty(col.DbInsertValue) == false)
|
||||
sb.Append(col.DbInsertValue);
|
||||
else
|
||||
{
|
||||
sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
|
||||
_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col, col.Attribute.MapType, val);
|
||||
object val = col.GetMapValue(d);
|
||||
if (_noneParameter)
|
||||
sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val));
|
||||
else
|
||||
{
|
||||
sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
|
||||
_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col, col.Attribute.MapType, val);
|
||||
}
|
||||
}
|
||||
++colidx2;
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ namespace FreeSql.Internal
|
||||
public abstract string StringConcat(string[] objs, Type[] types);
|
||||
public abstract string Mod(string left, string right, Type leftType, Type rightType);
|
||||
public abstract string Div(string left, string right, Type leftType, Type rightType);
|
||||
public abstract string Now { get; }
|
||||
public abstract string NowUtc { get; }
|
||||
public abstract string QuoteWriteParamter(Type type, string paramterName);
|
||||
public abstract string QuoteReadColumn(Type type, string columnName);
|
||||
|
||||
@ -126,7 +128,7 @@ namespace FreeSql.Internal
|
||||
if (trycol._Position != null) attr._Position = trycol.Position;
|
||||
if (trycol._CanInsert != null) attr._CanInsert = trycol.CanInsert;
|
||||
if (trycol._CanUpdate != null) attr._CanUpdate = trycol.CanUpdate;
|
||||
if (trycol.DbDefautValue != null) attr.DbDefautValue = trycol.DbDefautValue;
|
||||
if (trycol._ServerTime != null) attr._ServerTime = trycol._ServerTime;
|
||||
}
|
||||
var attrs = proto.GetCustomAttributes(typeof(ColumnAttribute), false);
|
||||
foreach (var tryattrobj in attrs)
|
||||
@ -145,7 +147,7 @@ namespace FreeSql.Internal
|
||||
if (tryattr._Position != null) attr._Position = tryattr.Position;
|
||||
if (tryattr._CanInsert != null) attr._CanInsert = tryattr.CanInsert;
|
||||
if (tryattr._CanUpdate != null) attr._CanUpdate = tryattr.CanUpdate;
|
||||
if (tryattr.DbDefautValue != null) attr.DbDefautValue = tryattr.DbDefautValue;
|
||||
if (tryattr._ServerTime != null) attr._ServerTime = tryattr.ServerTime;
|
||||
}
|
||||
ColumnAttribute ret = null;
|
||||
if (!string.IsNullOrEmpty(attr.Name)) ret = attr;
|
||||
@ -160,7 +162,7 @@ namespace FreeSql.Internal
|
||||
if (attr._Position != null) ret = attr;
|
||||
if (attr._CanInsert != null) ret = attr;
|
||||
if (attr._CanUpdate != null) ret = attr;
|
||||
if (attr.DbDefautValue != null) ret = attr;
|
||||
if (attr._ServerTime != null) ret = attr;
|
||||
if (ret != null && ret.MapType == null) ret.MapType = proto.PropertyType;
|
||||
return ret;
|
||||
}
|
||||
@ -343,8 +345,16 @@ namespace FreeSql.Internal
|
||||
/// <returns>Dict:key=属性名,value=注释</returns>
|
||||
public static Dictionary<string, string> GetProperyCommentBySummary(Type type)
|
||||
{
|
||||
var xmlPath = type.Assembly.Location.Replace(".dll", ".xml").Replace(".exe", ".xml");
|
||||
if (File.Exists(xmlPath) == false) return null;
|
||||
var regex = new Regex(@"\.(dll|exe)", RegexOptions.IgnoreCase);
|
||||
var xmlPath = regex.Replace(type.Assembly.Location, ".xml");
|
||||
if (File.Exists(xmlPath) == false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(type.Assembly.CodeBase)) return null;
|
||||
xmlPath = regex.Replace(type.Assembly.CodeBase, ".xml");
|
||||
if (xmlPath.StartsWith("file:///") && Uri.TryCreate(xmlPath, UriKind.Absolute, out var tryuri))
|
||||
xmlPath = tryuri.LocalPath;
|
||||
if (File.Exists(xmlPath) == false) return null;
|
||||
}
|
||||
|
||||
var dic = new Dictionary<string, string>();
|
||||
var sReader = new StringReader(File.ReadAllText(xmlPath));
|
||||
|
@ -14,6 +14,8 @@ namespace FreeSql.Internal.Model
|
||||
public ColumnAttribute Attribute { get; set; }
|
||||
public string Comment { get; internal set; }
|
||||
public string DbTypeText { get; internal set; }
|
||||
public string DbDefaultValue { get; internal set; }
|
||||
public string DbInsertValue { get; internal set; }
|
||||
public int DbSize { get; internal set; }
|
||||
public byte DbPrecision { get; internal set; }
|
||||
public byte DbScale { get; internal set; }
|
||||
|
@ -151,26 +151,48 @@ namespace FreeSql.Internal
|
||||
trytb.ColumnsByCsIgnore.Add(p.Name, col);
|
||||
continue;
|
||||
}
|
||||
if (entityDefault != null) colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(entityDefault, null);
|
||||
object defaultValue = null;
|
||||
if (entityDefault != null) defaultValue = trytb.Properties[p.Name].GetValue(entityDefault, null);
|
||||
if (p.PropertyType.IsEnum)
|
||||
{
|
||||
var isEqualsEnumValue = false;
|
||||
var enumValues = Enum.GetValues(p.PropertyType);
|
||||
for (var a = 0; a < enumValues.Length; a++)
|
||||
if (object.Equals(colattr.DbDefautValue, enumValues.GetValue(a)))
|
||||
if (object.Equals(defaultValue, enumValues.GetValue(a)))
|
||||
{
|
||||
isEqualsEnumValue = true;
|
||||
break;
|
||||
}
|
||||
if (isEqualsEnumValue == false && enumValues.Length > 0)
|
||||
colattr.DbDefautValue = enumValues.GetValue(0);
|
||||
defaultValue = enumValues.GetValue(0);
|
||||
}
|
||||
if (colattr.DbDefautValue != null && p.PropertyType != colattr.MapType) colattr.DbDefautValue = Utils.GetDataReaderValue(colattr.MapType, colattr.DbDefautValue);
|
||||
if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue;
|
||||
if (colattr.IsNullable == false && colattr.DbDefautValue == null)
|
||||
if (defaultValue != null && p.PropertyType != colattr.MapType) defaultValue = Utils.GetDataReaderValue(colattr.MapType, defaultValue);
|
||||
if (defaultValue == null) defaultValue = tp?.defaultValue;
|
||||
if (colattr.IsNullable == false && defaultValue == null)
|
||||
{
|
||||
var citype = colattr.MapType.IsNullableType() ? colattr.MapType.GetGenericArguments().FirstOrDefault() : colattr.MapType;
|
||||
colattr.DbDefautValue = citype.CreateInstanceGetDefaultValue();
|
||||
defaultValue = citype.CreateInstanceGetDefaultValue();
|
||||
}
|
||||
try
|
||||
{
|
||||
col.DbDefaultValue = common.GetNoneParamaterSqlValue(new List<DbParameter>(), colattr.MapType, defaultValue);
|
||||
}
|
||||
catch
|
||||
{
|
||||
col.DbDefaultValue = "NULL";
|
||||
}
|
||||
//if (defaultValue != null && colattr.MapType.NullableTypeOrThis() == typeof(DateTime))
|
||||
//{
|
||||
// var dt = (DateTime)defaultValue;
|
||||
// if (Math.Abs(dt.Subtract(DateTime.Now).TotalSeconds) < 60)
|
||||
// col.DbDefaultValue = common.Now;
|
||||
// else if (Math.Abs(dt.Subtract(DateTime.UtcNow).TotalSeconds) < 60)
|
||||
// col.DbDefaultValue = common.NowUtc;
|
||||
//}
|
||||
if (colattr._ServerTime != null && new[] { typeof(DateTime), typeof(DateTimeOffset) }.Contains(colattr.MapType.NullableTypeOrThis()))
|
||||
{
|
||||
col.DbDefaultValue = colattr.ServerTime == DateTimeKind.Local ? common.Now : common.NowUtc;
|
||||
col.DbInsertValue = colattr.ServerTime == DateTimeKind.Local ? common.Now : common.NowUtc;
|
||||
}
|
||||
|
||||
trytb.Columns.Add(colattr.Name, col);
|
||||
@ -1584,7 +1606,11 @@ namespace FreeSql.Internal
|
||||
Expression.Block(
|
||||
new[] { arrNewExp, arrExp, arrLenExp, arrXExp, arrReadValExp },
|
||||
Expression.Assign(arrExp, Expression.TypeAs(valueExp, typeof(Array))),
|
||||
Expression.Assign(arrLenExp, Expression.Call(arrExp, MethodArrayGetLength, Expression.Constant(0))),
|
||||
Expression.IfThenElse(
|
||||
Expression.Equal(arrExp, Expression.Constant(null)),
|
||||
Expression.Assign(arrLenExp, Expression.Constant(0)),
|
||||
Expression.Assign(arrLenExp, Expression.Call(arrExp, MethodArrayGetLength, Expression.Constant(0)))
|
||||
),
|
||||
Expression.Assign(arrXExp, Expression.Constant(0)),
|
||||
Expression.Assign(arrNewExp, Expression.NewArrayBounds(elementType, arrLenExp)),
|
||||
Expression.Loop(
|
||||
|
Reference in New Issue
Block a user