Browse Source

Apewer-6.5.9

dev
王厅 4 years ago
parent
commit
a239e71046
  1. 24
      Apewer.Source/Source/SqlClient.cs
  2. 2
      Apewer.Windows/_Extensions.cs
  3. 2
      Apewer/Apewer.props
  4. 60
      Apewer/ObjectSet.cs
  5. 2
      Apewer/RuntimeUtility.cs
  6. 11
      Apewer/Source/IQuery.cs
  7. 55
      Apewer/Source/Query.cs
  8. 115
      Apewer/Source/SourceUtility.cs
  9. 13
      Apewer/Source/TableStructure.cs
  10. 5
      Apewer/Web/ApiOptions.cs
  11. 3
      Apewer/_Extensions.cs
  12. 4
      ChangeLog.md

24
Apewer.Source/Source/SqlClient.cs

@ -378,11 +378,12 @@ namespace Apewer.Source
} }
/// <summary>创建数据库,返回错误信息。</summary> /// <summary>创建数据库,返回错误信息。</summary>
/// <param name="storeName">数据库名称。</param> /// <param name="name">数据库名称。</param>
/// <param name="logMaxSizeMB">日志文件的最大 MB 数,指定非正数将不限制增长。</param>
/// <returns>成功时候返回 NULL 值,失败时返回错误信息。</returns> /// <returns>成功时候返回 NULL 值,失败时返回错误信息。</returns>
public string CreateStore(string storeName) public string CreateStore(string name, int logMaxSizeMB = 1024)
{ {
var store = storeName.Escape().ToTrim(); var store = name.Escape().ToTrim();
if (store.IsEmpty()) return "创建失败:未指定数据库名称。"; if (store.IsEmpty()) return "创建失败:未指定数据库名称。";
if (ConnectionString.IsEmpty()) return "创建失败:未指定数据库连接方式。"; if (ConnectionString.IsEmpty()) return "创建失败:未指定数据库连接方式。";
@ -402,13 +403,14 @@ namespace Apewer.Source
var ldfPath = Path.Combine(dir, store) + "_log.ldf"; var ldfPath = Path.Combine(dir, store) + "_log.ldf";
// 创建库。 // 创建库。
var maxLog = logMaxSizeMB > 0 ? $"{logMaxSizeMB}MB" : "UNLIMITED";
var sql1 = $@" var sql1 = $@"
CREATE DATABASE [{store}] CREATE DATABASE [{store}]
ON PRIMARY ON PRIMARY
( (
NAME = N'{store}', NAME = N'{store}',
FILENAME = N'{mdfPath}', FILENAME = N'{mdfPath}',
SIZE = 8192KB, SIZE = 4MB,
MAXSIZE = UNLIMITED, MAXSIZE = UNLIMITED,
FILEGROWTH = 4MB FILEGROWTH = 4MB
) )
@ -416,19 +418,23 @@ LOG ON
( (
NAME = N'{store}_log', NAME = N'{store}_log',
FILENAME = N'{ldfPath}', FILENAME = N'{ldfPath}',
SIZE = 8MB, SIZE = 1MB,
MAXSIZE = 1024MB, MAXSIZE = {maxLog},
FILEGROWTH = 4MB FILEGROWTH = 1MB
) )
COLLATE Chinese_PRC_CI_AS COLLATE Chinese_PRC_CI_AS
"; ";
var create = source.Execute(sql1, null, false); var create = source.Execute(sql1, null, false);
if (!create.Success) return TextUtility.Merge("创建失败:", create.Message); if (!create.Success) return TextUtility.Merge("创建失败:", create.Message);
// 设兼容性级别。 // 设兼容性级别。
var sql2 = $"ALTER DATABASE [{store}] SET COMPATIBILITY_LEVEL = 0"; var sql2 = $"alter database [{store}] set compatibility_level = 0";
source.Execute(sql2, null, false); source.Execute(sql2, null, false);
// 设置恢复默认为“简单”
var sql3 = $"alter database [{store}] set recovery simple";
source.Execute(sql3, null, false);
return null; return null;
} }
} }

2
Apewer.Windows/_Extensions.cs

@ -4,7 +4,7 @@ using System;
using System.Windows.Forms; using System.Windows.Forms;
/// <summary>扩展方法。</summary> /// <summary>扩展方法。</summary>
public static class Extensions public static class Extensions_Apewer_Windows
{ {
#region Surface #region Surface

2
Apewer/Apewer.props

@ -9,7 +9,7 @@
<Description></Description> <Description></Description>
<RootNamespace>Apewer</RootNamespace> <RootNamespace>Apewer</RootNamespace>
<Product>Apewer Libraries</Product> <Product>Apewer Libraries</Product>
<Version>6.5.8</Version> <Version>6.5.9</Version>
</PropertyGroup> </PropertyGroup>
<!-- 生成 --> <!-- 生成 -->

60
Apewer/ObjectSet.cs

@ -16,54 +16,35 @@ namespace Apewer
{ {
/// <summary></summary> /// <summary></summary>
public ObjectSet(bool autoTrim) public ObjectSet(bool trimKey = false) : base(trimKey) { }
{
AutoTrim = autoTrim;
}
/// <summary></summary>
public ObjectSet() { }
} }
/// <summary>字典模型。</summary> /// <summary>字典模型。</summary>
[Serializable] [Serializable]
public partial class ObjectSet<T> // where T : class public partial class ObjectSet<T> : IToJson
{ {
private Dictionary<string, T> _origin; private Dictionary<string, T> _origin;
private bool _autotrim = false; private bool _trimkey = false;
private bool _locked = false; private bool _locked = false;
/// <summary>获取或设置字典内容。</summary> /// <summary>获取或设置字典内容。</summary>
public T this[string key] public T this[string key] { get { return Get(key); } set { Set(key, value); } }
{
get { return Get(key); }
set { Set(key, value); }
}
/// <summary>获取字典。</summary> /// <summary>获取字典。</summary>
internal Dictionary<string, T> Origin internal Dictionary<string, T> Origin { get { return _origin; } }
{
get { return _origin; }
}
internal bool Locked { get { return _locked; } set { _locked = value; } } internal bool Locked { get { return _locked; } set { _locked = value; } }
internal bool AutoTrim { get { return _autotrim; } set { _autotrim = value; } } internal bool TrimKey { get { return _trimkey; } set { _trimkey = value; } }
/// <summary>构造函数。</summary> /// <summary>构造函数。</summary>
public ObjectSet() public ObjectSet(bool trimKey = false)
{ {
_origin = new Dictionary<string, T>(); _trimkey = trimKey;
}
/// <summary>构造函数。</summary>
public ObjectSet(bool autoTrim)
{
_autotrim = autoTrim;
_origin = new Dictionary<string, T>(); _origin = new Dictionary<string, T>();
} }
@ -78,7 +59,7 @@ namespace Apewer
var value = default(T); var value = default(T);
if (key != null) if (key != null)
{ {
var k = _autotrim ? Trim(key) : key; var k = _trimkey ? Trim(key) : key;
lock (_origin) lock (_origin)
{ {
contains = _origin.ContainsKey(k); contains = _origin.ContainsKey(k);
@ -94,23 +75,28 @@ namespace Apewer
var success = false; var success = false;
if (key != null) if (key != null)
{ {
var k = _autotrim ? Trim(key) : key; var k = _trimkey ? Trim(key) : key;
lock (_origin) lock (_origin)
{ {
if (_origin.ContainsKey(k)) if (_origin.ContainsKey(k)) _origin[k] = value;
{ else _origin.Add(k, value);
_origin[k] = value;
}
else
{
_origin.Add(k, value);
}
success = true; success = true;
} }
} }
return success; return success;
} }
/// <summary>转换为 <see cref="Json"/> 对象。</summary>
public Json ToJson() => Json.From(_origin);
/// <summary>转换为 <see cref="Json"/> 字符串。</summary>
public override string ToString()
{
var json = ToJson();
if (json == null) return null;
return json.ToString(true);
}
} }
#if !NET20 #if !NET20

2
Apewer/RuntimeUtility.cs

@ -415,7 +415,7 @@ namespace Apewer
/// <summary>判断指定对象是否为默认值。</summary> /// <summary>判断指定对象是否为默认值。</summary>
public static bool IsDefault(object value) public static bool IsDefault(object value)
{ {
if (value == null) return true; if (value.IsNull()) return true;
var type = value.GetType(); var type = value.GetType();
if (type.IsValueType) return value.Equals(Activator.CreateInstance(type)); if (type.IsValueType) return value.Equals(Activator.CreateInstance(type));
return false; return false;

11
Apewer/Source/IQuery.cs

@ -7,7 +7,7 @@ namespace Apewer.Source
{ {
/// <summary>查询数据表。</summary> /// <summary>查询数据表。</summary>
public interface IQuery : IDisposable public interface IQuery : IDisposable, IToJson
{ {
#region 结果集的属性。 #region 结果集的属性。
@ -29,7 +29,7 @@ namespace Apewer.Source
#endregion #endregion
#region 以对象获取结果集中的内容 #region 读取 DateTime 对象
/// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary> /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
object Value(); object Value();
@ -54,6 +54,13 @@ namespace Apewer.Source
#endregion #endregion
#region 模型化。
/// <summary>转换为模型数组。</summary>
ObjectSet[] ToArray();
#endregion
} }
} }

55
Apewer/Source/Query.cs

@ -240,7 +240,7 @@ namespace Apewer.Source
#endregion #endregion
#region IToJson #region 模型化、IToJson
/// <summary>转换为 Json 对象。</summary> /// <summary>转换为 Json 对象。</summary>
public Json ToJson() public Json ToJson()
@ -251,7 +251,7 @@ namespace Apewer.Source
var table = _table; var table = _table;
if (!_disposed && table != null) if (!_disposed && table != null)
{ {
var columnsCount = _table.Columns.Count; var columnsCount = table.Columns.Count;
for (var c = 0; c < columnsCount; c++) for (var c = 0; c < columnsCount; c++)
{ {
var dc = table.Columns[c]; var dc = table.Columns[c];
@ -262,7 +262,7 @@ namespace Apewer.Source
} }
var rowsCount = table.Rows.Count; var rowsCount = table.Rows.Count;
for (var r = 0; r < _table.Rows.Count; r++) for (var r = 0; r < rowsCount; r++)
{ {
var row = Json.NewArray(); var row = Json.NewArray();
for (var c = 0; c < columnsCount; c++) for (var c = 0; c < columnsCount; c++)
@ -294,6 +294,54 @@ namespace Apewer.Source
return jsonObject; return jsonObject;
} }
/// <summary>转换为模型数组。</summary>
public ObjectSet[] ToArray()
{
var oss = null as ObjectSet[];
var table = _table;
if (!_disposed && table != null)
{
var width = table.Columns.Count;
var names = new string[width];
for (var c = 0; c < width; c++)
{
var name = table.Columns[c].ColumnName;
if (name.IsEmpty()) continue;
if (names.Contains(name)) continue;
names[c] = name;
}
var unnamed = 1;
for (var c = 0; c < width; c++)
{
if (names[c] != null) continue;
while (true)
{
var name = "unnamed_" + unnamed.ToString();
unnamed++;
if (names.Contains(name)) continue;
names[c] = name;
break;
}
}
var height = table.Rows.Count;
oss = new ObjectSet[height];
for (var r = 0; r < height; r++)
{
var os = new ObjectSet();
var dict = os.Origin;
for (var c = 0; c < width; c++)
{
var v = Value(r, c);
dict.Add(names[c], v.IsNull() ? null : v);
}
oss[r] = os;
}
}
return oss;
}
#endregion #endregion
#region Static #region Static
@ -303,6 +351,7 @@ namespace Apewer.Source
private static T TextFormatter<T>(object input) => (T)(Text(input) as object); private static T TextFormatter<T>(object input) => (T)(Text(input) as object);
private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } } private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } }
#endregion #endregion
#region Extension #region Extension

115
Apewer/Source/SourceUtility.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Reflection;
using System.Text; using System.Text;
using static Apewer.NumberUtility; using static Apewer.NumberUtility;
@ -123,71 +124,83 @@ namespace Apewer.Source
var properties = model.GetProperties(); var properties = model.GetProperties();
foreach (var property in properties) foreach (var property in properties)
{ {
// 必须有 setter 访问器。
var setter = property.GetSetMethod();
if (setter == null) continue;
// 在表结构中检查,是否包含此属性,并获取 ColumnAttribute。 // 在表结构中检查,是否包含此属性,并获取 ColumnAttribute 中的 Field。
var attribute = null as ColumnAttribute; var field = null as string;
for (var j = 0; j < columns.Length; j++) for (var j = 0; j < columns.Length; j++)
{ {
if (columns[j].PropertyName == property.Name) if (columns[j].PropertyName == property.Name)
{ {
attribute = columns[j]; field = columns[j].Field;
break; break;
} }
} }
if (attribute == null) continue; if (field == null)
// 读取值。
var value = query.Value(r, attribute.Field);
if (value == null) continue;
if (value.Equals(DBNull.Value)) continue;
// 根据属性类型设置值。
var pt = property.PropertyType;
if (pt.Equals(typeof(object))) setter.Invoke(record, new object[] { value });
else if (pt.Equals(typeof(byte[]))) setter.Invoke(record, new object[] { (byte[])value });
else if (pt.Equals(typeof(string))) setter.Invoke(record, new object[] { value.ToString() });
else if (pt.Equals(typeof(DateTime))) setter.Invoke(record, new object[] { value });
else if (pt.Equals(typeof(byte))) setter.Invoke(record, new object[] { Byte(value) });
else if (pt.Equals(typeof(sbyte))) setter.Invoke(record, new object[] { SByte(value) });
else if (pt.Equals(typeof(short))) setter.Invoke(record, new object[] { Int16(value) });
else if (pt.Equals(typeof(ushort))) setter.Invoke(record, new object[] { UInt16(value) });
else if (pt.Equals(typeof(int))) setter.Invoke(record, new object[] { Int32(value) });
else if (pt.Equals(typeof(uint))) setter.Invoke(record, new object[] { UInt32(value) });
else if (pt.Equals(typeof(long))) setter.Invoke(record, new object[] { Int64(value) });
else if (pt.Equals(typeof(ulong))) setter.Invoke(record, new object[] { UInt64(value) });
else if (pt.Equals(typeof(float))) setter.Invoke(record, new object[] { Single(value) });
else if (pt.Equals(typeof(double))) setter.Invoke(record, new object[] { Double(value) });
else if (pt.Equals(typeof(decimal))) setter.Invoke(record, new object[] { Decimal(value) });
else if (pt.Equals(typeof(Nullable<DateTime>))) setter.Invoke(record, new object[] { new Nullable<DateTime>((DateTime)value) });
else if (pt.Equals(typeof(Nullable<byte>))) setter.Invoke(record, new object[] { new Nullable<byte>(Byte(value)) });
else if (pt.Equals(typeof(Nullable<sbyte>))) setter.Invoke(record, new object[] { new Nullable<sbyte>(SByte(value)) });
else if (pt.Equals(typeof(Nullable<short>))) setter.Invoke(record, new object[] { new Nullable<short>(Int16(value)) });
else if (pt.Equals(typeof(Nullable<ushort>))) setter.Invoke(record, new object[] { new Nullable<int>(UInt16(value)) });
else if (pt.Equals(typeof(Nullable<int>))) setter.Invoke(record, new object[] { new Nullable<int>(Int32(value)) });
else if (pt.Equals(typeof(Nullable<uint>))) setter.Invoke(record, new object[] { new Nullable<uint>(UInt32(value)) });
else if (pt.Equals(typeof(Nullable<long>))) setter.Invoke(record, new object[] { new Nullable<long>(Int64(value)) });
else if (pt.Equals(typeof(Nullable<ulong>))) setter.Invoke(record, new object[] { new Nullable<ulong>(UInt64(value)) });
else if (pt.Equals(typeof(Nullable<float>))) setter.Invoke(record, new object[] { new Nullable<float>(Single(value)) });
else if (pt.Equals(typeof(Nullable<double>))) setter.Invoke(record, new object[] { new Nullable<double>(Double(value)) });
else if (pt.Equals(typeof(Nullable<decimal>))) setter.Invoke(record, new object[] { new Nullable<decimal>(Decimal(value)) });
else
{ {
try if (ts.Attribute != null && ts.AllProperties) continue;
{ field = property.Name;
setter.Invoke(record, new object[] { query.Value(r, attribute.Field) });
}
catch { }
} }
var value = query.Value(r, field);
var setted = Set(record, property, value);
} }
return record; return record;
} }
static bool Set(object record, PropertyInfo property, object value)
{
// 读取值。
if (value == null) return false;
if (value.Equals(DBNull.Value)) return false;
// 必须有 setter 访问器。
var setter = property.GetSetMethod();
if (setter == null) return false;
// 根据属性类型设置值。
var pt = property.PropertyType;
if (pt.Equals(typeof(object))) setter.Invoke(record, new object[] { value });
else if (pt.Equals(typeof(byte[]))) setter.Invoke(record, new object[] { (byte[])value });
else if (pt.Equals(typeof(string))) setter.Invoke(record, new object[] { value.ToString() });
else if (pt.Equals(typeof(DateTime))) setter.Invoke(record, new object[] { value });
else if (pt.Equals(typeof(byte))) setter.Invoke(record, new object[] { Byte(value) });
else if (pt.Equals(typeof(sbyte))) setter.Invoke(record, new object[] { SByte(value) });
else if (pt.Equals(typeof(short))) setter.Invoke(record, new object[] { Int16(value) });
else if (pt.Equals(typeof(ushort))) setter.Invoke(record, new object[] { UInt16(value) });
else if (pt.Equals(typeof(int))) setter.Invoke(record, new object[] { Int32(value) });
else if (pt.Equals(typeof(uint))) setter.Invoke(record, new object[] { UInt32(value) });
else if (pt.Equals(typeof(long))) setter.Invoke(record, new object[] { Int64(value) });
else if (pt.Equals(typeof(ulong))) setter.Invoke(record, new object[] { UInt64(value) });
else if (pt.Equals(typeof(float))) setter.Invoke(record, new object[] { Single(value) });
else if (pt.Equals(typeof(double))) setter.Invoke(record, new object[] { Double(value) });
else if (pt.Equals(typeof(decimal))) setter.Invoke(record, new object[] { Decimal(value) });
else if (pt.Equals(typeof(Nullable<DateTime>))) setter.Invoke(record, new object[] { new Nullable<DateTime>((DateTime)value) });
else if (pt.Equals(typeof(Nullable<byte>))) setter.Invoke(record, new object[] { new Nullable<byte>(Byte(value)) });
else if (pt.Equals(typeof(Nullable<sbyte>))) setter.Invoke(record, new object[] { new Nullable<sbyte>(SByte(value)) });
else if (pt.Equals(typeof(Nullable<short>))) setter.Invoke(record, new object[] { new Nullable<short>(Int16(value)) });
else if (pt.Equals(typeof(Nullable<ushort>))) setter.Invoke(record, new object[] { new Nullable<int>(UInt16(value)) });
else if (pt.Equals(typeof(Nullable<int>))) setter.Invoke(record, new object[] { new Nullable<int>(Int32(value)) });
else if (pt.Equals(typeof(Nullable<uint>))) setter.Invoke(record, new object[] { new Nullable<uint>(UInt32(value)) });
else if (pt.Equals(typeof(Nullable<long>))) setter.Invoke(record, new object[] { new Nullable<long>(Int64(value)) });
else if (pt.Equals(typeof(Nullable<ulong>))) setter.Invoke(record, new object[] { new Nullable<ulong>(UInt64(value)) });
else if (pt.Equals(typeof(Nullable<float>))) setter.Invoke(record, new object[] { new Nullable<float>(Single(value)) });
else if (pt.Equals(typeof(Nullable<double>))) setter.Invoke(record, new object[] { new Nullable<double>(Double(value)) });
else if (pt.Equals(typeof(Nullable<decimal>))) setter.Invoke(record, new object[] { new Nullable<decimal>(Decimal(value)) });
else
{
try
{
setter.Invoke(record, new object[] { value });
return true;
}
catch { }
}
return false;
}
#endregion #endregion
#region IOrm #region IOrm

13
Apewer/Source/TableStructure.cs

@ -120,12 +120,15 @@ namespace Apewer.Source
ts._attribute = ta; ts._attribute = ta;
ts._key = key; ts._key = key;
ts._flag = flag; ts._flag = flag;
ts._name = ta.Name;
ts._description = ta.Description;
ts._allprops = ta.AllProperties;
ts._independent = ta.Independent;
ts._columns = columns; ts._columns = columns;
ts._model = model; ts._model = model;
if (ta != null)
{
ts._name = ta.Name;
ts._description = ta.Description;
ts._allprops = ta.AllProperties;
ts._independent = ta.Independent;
}
// 加入缓存。 // 加入缓存。
if (useCache) if (useCache)
@ -168,7 +171,7 @@ namespace Apewer.Source
{ {
if (!str.StartsWith("_")) str = TextUtility.Merge("_", str); if (!str.StartsWith("_")) str = TextUtility.Merge("_", str);
} }
return str; return str;
} }

5
Apewer/Web/ApiOptions.cs

@ -105,7 +105,10 @@ namespace Apewer.Web
/// <br />WithDuration = TRUE /// <br />WithDuration = TRUE
/// <br />WithParameters = TRUE /// <br />WithParameters = TRUE
/// </remarks> /// </remarks>
public ApiOptions() => Debug(); public ApiOptions()
{
Debug();
}
[Conditional("DEBUG")] [Conditional("DEBUG")]
void Debug() void Debug()

3
Apewer/_Extensions.cs

@ -21,6 +21,9 @@ public static class Extensions_Apewer
/// <summary>不是 NULL 值。</summary> /// <summary>不是 NULL 值。</summary>
public static bool NotNull(this object @this) => @this != null && !@this.Equals(DBNull.Value); public static bool NotNull(this object @this) => @this != null && !@this.Equals(DBNull.Value);
/// <summary>是默认值。</summary>
public static bool IsDefault(this object @this) => RuntimeUtility.IsDefault(@this);
#region Class Utility #region Class Utility
/// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary> /// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary>

4
ChangeLog.md

@ -1,6 +1,10 @@
 
### 最新提交 ### 最新提交
### 6.5.9
- Source:修正 Query<T> 填充无特性类型时的报错;
- Source:新增 Query.ToArray 方法,支持 dynamic。
### 6.5.8 ### 6.5.8
- Source:SqlClient 新增 CreateStore 方法,支持创建数据库。 - Source:SqlClient 新增 CreateStore 方法,支持创建数据库。

Loading…
Cancel
Save