- 增加 实体特性 [Column(ServerTime = DateTimeKind.Utc)] 使用数据库时间执行插入数据;

- 修复 ToList(a => new Dto { .. }) 在使用 GroupBy 之后报错的 bug;
- 修复 注释迁移到数据库,在 asp.net 4.7 无效的问题;
This commit is contained in:
28810
2019-11-25 17:30:36 +08:00
parent 27acd4da08
commit 01b31c095b
49 changed files with 332 additions and 146 deletions

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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;

View File

@ -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;
}

View File

@ -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>Dictkey=属性名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));

View File

@ -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; }

View File

@ -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(