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>
/// <param name="storeName">数据库名称。</param>
/// <param name="name">数据库名称。</param>
/// <param name="logMaxSizeMB">日志文件的最大 MB 数,指定非正数将不限制增长。</param>
/// <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 (ConnectionString.IsEmpty()) return "创建失败:未指定数据库连接方式。";
@ -402,13 +403,14 @@ namespace Apewer.Source
var ldfPath = Path.Combine(dir, store) + "_log.ldf";
// 创建库。
var maxLog = logMaxSizeMB > 0 ? $"{logMaxSizeMB}MB" : "UNLIMITED";
var sql1 = $@"
CREATE DATABASE [{store}]
ON PRIMARY
(
NAME = N'{store}',
FILENAME = N'{mdfPath}',
SIZE = 8192KB,
SIZE = 4MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 4MB
)
@ -416,19 +418,23 @@ LOG ON
(
NAME = N'{store}_log',
FILENAME = N'{ldfPath}',
SIZE = 8MB,
MAXSIZE = 1024MB,
FILEGROWTH = 4MB
SIZE = 1MB,
MAXSIZE = {maxLog},
FILEGROWTH = 1MB
)
COLLATE Chinese_PRC_CI_AS
";
var create = source.Execute(sql1, null, false);
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);
// 设置恢复默认为“简单”
var sql3 = $"alter database [{store}] set recovery simple";
source.Execute(sql3, null, false);
return null;
}
}

2
Apewer.Windows/_Extensions.cs

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

2
Apewer/Apewer.props

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

60
Apewer/ObjectSet.cs

@ -16,54 +16,35 @@ namespace Apewer
{
/// <summary></summary>
public ObjectSet(bool autoTrim)
{
AutoTrim = autoTrim;
}
/// <summary></summary>
public ObjectSet() { }
public ObjectSet(bool trimKey = false) : base(trimKey) { }
}
/// <summary>字典模型。</summary>
[Serializable]
public partial class ObjectSet<T> // where T : class
public partial class ObjectSet<T> : IToJson
{
private Dictionary<string, T> _origin;
private bool _autotrim = false;
private bool _trimkey = false;
private bool _locked = false;
/// <summary>获取或设置字典内容。</summary>
public T this[string key]
{
get { return Get(key); }
set { Set(key, value); }
}
public T this[string key] { get { return Get(key); } set { Set(key, value); } }
/// <summary>获取字典。</summary>
internal Dictionary<string, T> Origin
{
get { return _origin; }
}
internal Dictionary<string, T> Origin { get { return _origin; } }
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>
public ObjectSet()
public ObjectSet(bool trimKey = false)
{
_origin = new Dictionary<string, T>();
}
/// <summary>构造函数。</summary>
public ObjectSet(bool autoTrim)
{
_autotrim = autoTrim;
_trimkey = trimKey;
_origin = new Dictionary<string, T>();
}
@ -78,7 +59,7 @@ namespace Apewer
var value = default(T);
if (key != null)
{
var k = _autotrim ? Trim(key) : key;
var k = _trimkey ? Trim(key) : key;
lock (_origin)
{
contains = _origin.ContainsKey(k);
@ -94,23 +75,28 @@ namespace Apewer
var success = false;
if (key != null)
{
var k = _autotrim ? Trim(key) : key;
var k = _trimkey ? Trim(key) : key;
lock (_origin)
{
if (_origin.ContainsKey(k))
{
_origin[k] = value;
}
else
{
_origin.Add(k, value);
}
if (_origin.ContainsKey(k)) _origin[k] = value;
else _origin.Add(k, value);
success = true;
}
}
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

2
Apewer/RuntimeUtility.cs

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

11
Apewer/Source/IQuery.cs

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

55
Apewer/Source/Query.cs

@ -240,7 +240,7 @@ namespace Apewer.Source
#endregion
#region IToJson
#region 模型化、IToJson
/// <summary>转换为 Json 对象。</summary>
public Json ToJson()
@ -251,7 +251,7 @@ namespace Apewer.Source
var table = _table;
if (!_disposed && table != null)
{
var columnsCount = _table.Columns.Count;
var columnsCount = table.Columns.Count;
for (var c = 0; c < columnsCount; c++)
{
var dc = table.Columns[c];
@ -262,7 +262,7 @@ namespace Apewer.Source
}
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();
for (var c = 0; c < columnsCount; c++)
@ -294,6 +294,54 @@ namespace Apewer.Source
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
#region Static
@ -303,6 +351,7 @@ namespace Apewer.Source
private static T TextFormatter<T>(object input) => (T)(Text(input) as object);
private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } }
#endregion
#region Extension

115
Apewer/Source/SourceUtility.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using static Apewer.NumberUtility;
@ -123,71 +124,83 @@ namespace Apewer.Source
var properties = model.GetProperties();
foreach (var property in properties)
{
// 必须有 setter 访问器。
var setter = property.GetSetMethod();
if (setter == null) continue;
// 在表结构中检查,是否包含此属性,并获取 ColumnAttribute。
var attribute = null as ColumnAttribute;
// 在表结构中检查,是否包含此属性,并获取 ColumnAttribute 中的 Field。
var field = null as string;
for (var j = 0; j < columns.Length; j++)
{
if (columns[j].PropertyName == property.Name)
{
attribute = columns[j];
field = columns[j].Field;
break;
}
}
if (attribute == null) continue;
// 读取值。
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
if (field == null)
{
try
{
setter.Invoke(record, new object[] { query.Value(r, attribute.Field) });
}
catch { }
if (ts.Attribute != null && ts.AllProperties) continue;
field = property.Name;
}
var value = query.Value(r, field);
var setted = Set(record, property, value);
}
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
#region IOrm

13
Apewer/Source/TableStructure.cs

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

5
Apewer/Web/ApiOptions.cs

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

3
Apewer/_Extensions.cs

@ -21,6 +21,9 @@ public static class Extensions_Apewer
/// <summary>不是 NULL 值。</summary>
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
/// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary>

4
ChangeLog.md

@ -1,6 +1,10 @@

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

Loading…
Cancel
Save