|
|
@ -13,37 +13,45 @@ namespace Apewer.Source |
|
|
|
|
|
|
|
#region As
|
|
|
|
|
|
|
|
private static T[] As<T>(IRecord[] input) where T : IRecord |
|
|
|
/// <summary>转换模型类型。</summary>
|
|
|
|
public static TDst[] As<TSrc, TDst>(this TSrc[] input) where TDst : class |
|
|
|
{ |
|
|
|
if (input == null) return null; |
|
|
|
var count = input.Length; |
|
|
|
var output = new T[count]; |
|
|
|
var output = new TDst[count]; |
|
|
|
for (var i = 0; i < count; i++) |
|
|
|
{ |
|
|
|
var record = input[i]; |
|
|
|
if (record == null) continue; |
|
|
|
var t = (T)record; |
|
|
|
output[i] = t; |
|
|
|
var item = input[i]; |
|
|
|
if (item == null) continue; |
|
|
|
output[i] = item as TDst; // 此处可能抛出异常。
|
|
|
|
} |
|
|
|
return output; |
|
|
|
} |
|
|
|
|
|
|
|
private static Result<T> As<T>(Result<IRecord> input) where T : class, IRecord, new() |
|
|
|
/// <summary>转换模型类型。</summary>
|
|
|
|
public static Result<TDst> As<TSrc, TDst>(this Result<TSrc> input) where TDst : class |
|
|
|
{ |
|
|
|
if (input == null) return null; |
|
|
|
if (!input.HasValue) return new Result<T>(input.Code, input.Message); |
|
|
|
var value = input.Value as T; |
|
|
|
return new Result<T>(value); |
|
|
|
if (!input.HasValue) return new Result<TDst>(input.Code, input.Message); |
|
|
|
var value = input.Value as TDst; |
|
|
|
if (value == null) |
|
|
|
{ |
|
|
|
var src = input.Value.GetType().FullName; |
|
|
|
var dst = typeof(TDst).FullName; |
|
|
|
return new Result<TDst>($"无法将记录从转换 {src} 到 {dst}。"); |
|
|
|
} |
|
|
|
return new Result<TDst>(value); |
|
|
|
} |
|
|
|
|
|
|
|
private static Result<T[]> As<T>(Result<IRecord[]> input) where T : class, IRecord, new() |
|
|
|
/// <summary>转换模型类型。</summary>
|
|
|
|
public static Result<TDst[]> As<TSrc, TDst>(this Result<TSrc[]> input) where TDst : class |
|
|
|
{ |
|
|
|
if (input == null) return null; |
|
|
|
if (!input.HasValue) return new Result<T[]>(input.Code, input.Message); |
|
|
|
if (!input.HasValue) return new Result<TDst[]>(input.Code, input.Message); |
|
|
|
var count = input.Value.Length; |
|
|
|
var output = new T[count]; |
|
|
|
for (var i = 0; i < count; i++) output[i] = input.Value[i] as T; |
|
|
|
return new Result<T[]>(output); |
|
|
|
var output = new TDst[count]; |
|
|
|
for (var i = 0; i < count; i++) output[i] = input.Value[i] as TDst; |
|
|
|
return new Result<TDst[]>(output); |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
@ -51,16 +59,18 @@ namespace Apewer.Source |
|
|
|
#region IQuery -> IRecord
|
|
|
|
|
|
|
|
/// <summary>读取所有行,生成列表。</summary>
|
|
|
|
public static T[] Fill<T>(IQuery query) where T : class, IRecord, new() => As<T>(Fill(query, typeof(T))); |
|
|
|
public static T[] Fill<T>(IQuery query) where T : class, new() => As<object, T>(Fill(query, typeof(T))); |
|
|
|
|
|
|
|
/// <summary>读取所有行填充到 T,组成 T[]。</summary>
|
|
|
|
public static IRecord[] Fill(IQuery query, Type model) |
|
|
|
public static object[] Fill(IQuery query, Type model) |
|
|
|
{ |
|
|
|
if (query == null) return new IRecord[0]; |
|
|
|
if (model == null) return new IRecord[0]; |
|
|
|
if (query == null) return new object[0]; |
|
|
|
if (model == null) return new object[0]; |
|
|
|
|
|
|
|
var ts = TableStructure.Parse(model); |
|
|
|
var output = new IRecord[query.Rows]; |
|
|
|
if (ts == null) return new object[0]; |
|
|
|
|
|
|
|
var output = new object[query.Rows]; |
|
|
|
for (int r = 0; r < query.Rows; r++) output[r] = Row(query, r, model, ts); |
|
|
|
return output; |
|
|
|
} |
|
|
@ -94,6 +104,7 @@ namespace Apewer.Source |
|
|
|
|
|
|
|
/// <summary>将 Query 的行,填充到模型实体。</summary>
|
|
|
|
/// <remarks>填充失败时返回 NULL 值。</remarks>
|
|
|
|
/// <exception cref="Exception"></exception>
|
|
|
|
public static IRecord Row(IQuery query, int rowIndex, Type model, TableStructure structure) |
|
|
|
{ |
|
|
|
// 检查参数。
|
|
|
@ -210,27 +221,27 @@ namespace Apewer.Source |
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
|
/// <param name="model">记录模型。</param>
|
|
|
|
/// <param name="sql">SQL 语句。</param>
|
|
|
|
public static Result<IRecord[]> Query(IDbClientAdo database, Type model, string sql) |
|
|
|
public static Result<object[]> Query(IDbClientAdo database, Type model, string sql) |
|
|
|
{ |
|
|
|
if (database == null) return new Result<IRecord[]>("数据库无效。"); |
|
|
|
if (model == null) return new Result<IRecord[]>("模型类型无效。"); |
|
|
|
if (string.IsNullOrEmpty(sql)) return new Result<IRecord[]>("SQL 语句无效。"); |
|
|
|
if (database == null) return new Result<object[]>("数据库无效。"); |
|
|
|
if (model == null) return new Result<object[]>("模型类型无效。"); |
|
|
|
if (string.IsNullOrEmpty(sql)) return new Result<object[]>("SQL 语句无效。"); |
|
|
|
using (var query = database.Query(sql) as Query) |
|
|
|
{ |
|
|
|
if (query == null) return new Result<IRecord[]>("查询实例无效。"); |
|
|
|
if (query == null) return new Result<object[]>("查询实例无效。"); |
|
|
|
if (query.Table == null) |
|
|
|
{ |
|
|
|
if (!string.IsNullOrEmpty(query.Message)) return new Result<IRecord[]>(query.Message); |
|
|
|
return new Result<IRecord[]>("查询实例不包含数据表。"); |
|
|
|
if (!string.IsNullOrEmpty(query.Message)) return new Result<object[]>(query.Message); |
|
|
|
return new Result<object[]>("查询实例不包含数据表。"); |
|
|
|
} |
|
|
|
try |
|
|
|
{ |
|
|
|
var array = Fill(query, model); |
|
|
|
return new Result<IRecord[]>(array); |
|
|
|
return new Result<object[]>(array); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
return new Result<IRecord[]>(ex); |
|
|
|
return new Result<object[]>(ex); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -239,24 +250,24 @@ namespace Apewer.Source |
|
|
|
/// <typeparam name="T">记录模型。</typeparam>
|
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
|
/// <param name="sql">SQL 语句。</param>
|
|
|
|
public static Result<T[]> Query<T>(IDbClientAdo database, string sql) where T : class, IRecord, new() => As<T>(Query(database, typeof(T), sql)); |
|
|
|
public static Result<T[]> Query<T>(IDbClientAdo database, string sql) where T : class, new() => As<object, T>(Query(database, typeof(T), sql)); |
|
|
|
|
|
|
|
/// <summary>查询记录。</summary>
|
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
|
/// <param name="model">记录模型。</param>
|
|
|
|
/// <param name="sqlGetter">生成 SQL 语句的函数,传入参数为表名。</param>
|
|
|
|
public static Result<IRecord[]> Query(IDbClientAdo database, Type model, Func<string, string> sqlGetter) |
|
|
|
public static Result<object[]> Query(IDbClientAdo database, Type model, Func<string, string> sqlGetter) |
|
|
|
{ |
|
|
|
if (sqlGetter == null) return new Result<IRecord[]>("SQL 语句获取函数无效。"); |
|
|
|
if (sqlGetter == null) return new Result<object[]>("SQL 语句获取函数无效。"); |
|
|
|
try |
|
|
|
{ |
|
|
|
var tableName = TableStructure.Parse(model).Name; |
|
|
|
if (string.IsNullOrEmpty(tableName)) return new Result<IRecord[]>("表名无效。"); |
|
|
|
if (string.IsNullOrEmpty(tableName)) return new Result<object[]>("表名无效。"); |
|
|
|
return Query(database, model, sqlGetter(tableName)); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
return new Result<IRecord[]>(ex); |
|
|
|
return new Result<object[]>(ex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -264,7 +275,7 @@ namespace Apewer.Source |
|
|
|
/// <typeparam name="T">记录模型。</typeparam>
|
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
|
/// <param name="sqlGetter">生成 SQL 语句的函数,传入参数为表名。</param>
|
|
|
|
public static Result<T[]> Query<T>(IDbClientAdo database, Func<string, string> sqlGetter) where T : class, IRecord, new() => As<T>(Query(database, typeof(T), sqlGetter)); |
|
|
|
public static Result<T[]> Query<T>(IDbClientAdo database, Func<string, string> sqlGetter) where T : class, new() => As<object, T>(Query(database, typeof(T), sqlGetter)); |
|
|
|
|
|
|
|
/// <summary>获取具有指定主键的记录。</summary>
|
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
@ -306,7 +317,7 @@ namespace Apewer.Source |
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
|
/// <param name="key">主键。</param>
|
|
|
|
/// <param name="sqlGetter">生成 SQL 语句的函数,传入参数为表名和主键值。</param>
|
|
|
|
public static Result<T> Get<T>(IDbClientAdo database, string key, Func<string, string, string> sqlGetter) where T : class, IRecord, new() => As<T>(Get(database, typeof(T), key, sqlGetter)); |
|
|
|
public static Result<T> Get<T>(IDbClientAdo database, string key, Func<string, string, string> sqlGetter) where T : class, IRecord, new() => As<IRecord, T>(Get(database, typeof(T), key, sqlGetter)); |
|
|
|
|
|
|
|
/// <summary>获取主键。</summary>
|
|
|
|
/// <param name="database">数据库对象。</param>
|
|
|
@ -380,6 +391,55 @@ namespace Apewer.Source |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Record
|
|
|
|
|
|
|
|
/// <summary>修复记录属性。</summary>
|
|
|
|
public static void FixProperties(object record) |
|
|
|
{ |
|
|
|
if (record == null) return; |
|
|
|
|
|
|
|
if (record is IRecord key) key.ResetKey(); |
|
|
|
|
|
|
|
if (record is IRecordMoment moment) |
|
|
|
{ |
|
|
|
var now = ClockUtility.LucidNow; |
|
|
|
if (string.IsNullOrEmpty(moment.Created)) moment.Created = now; |
|
|
|
if (string.IsNullOrEmpty(moment.Updated)) moment.Updated = now; |
|
|
|
} |
|
|
|
|
|
|
|
if (record is IRecordStamp stamp) |
|
|
|
{ |
|
|
|
var utc = ClockUtility.UtcStamp; |
|
|
|
if (stamp.Created == 0L) stamp.Created = utc; |
|
|
|
if (stamp.Updated == 0L) stamp.Updated = utc; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>设置 Updated 属性。</summary>
|
|
|
|
/// <returns>TRUE:设置成功;FALSE:设置失败。</returns>
|
|
|
|
public static bool SetUpdated(object record) |
|
|
|
{ |
|
|
|
if (record == null) return false; |
|
|
|
|
|
|
|
if (record is IRecordMoment moment) |
|
|
|
{ |
|
|
|
var now = ClockUtility.LucidNow; |
|
|
|
moment.Updated = now; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
if (record is IRecordStamp stamp) |
|
|
|
{ |
|
|
|
var utc = ClockUtility.UtcStamp; |
|
|
|
stamp.Updated = utc; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|