Browse Source

Apewer-6.5.8

dev
王厅 4 years ago
parent
commit
79dbf3f215
  1. 30
      Apewer.Source/Source/DbClient.cs
  2. 92
      Apewer.Source/Source/SqlClient.cs
  3. 2
      Apewer/Apewer.props
  4. 6
      Apewer/NetworkUtility.cs
  5. 36
      Apewer/Source/Query.cs
  6. 78
      Apewer/Source/SourceUtility.cs
  7. 9
      ChangeLog.md

30
Apewer.Source/Source/DbClient.cs

@ -338,36 +338,6 @@ namespace Apewer.Source
#region static
/// <summary>对文本转义,符合 SQL 安全性。可根据字段类型限制 UTF-8 字节数,默认为 0 时不限制字节数。</summary>
public static string Escape(string text, int bytes = 0)
{
if (text.IsEmpty()) return "";
var t = text ?? "";
t = t.Replace("\\", "\\\\");
t = t.Replace("'", "\\'");
t = t.Replace("\n", "\\n");
t = t.Replace("\r", "\\r");
t = t.Replace("\b", "\\b");
t = t.Replace("\t", "\\t");
t = t.Replace("\f", "\\f");
if (bytes > 5)
{
if (t.Bytes(Encoding.UTF8).Length > bytes)
{
while (true)
{
t = t.Substring(0, t.Length - 1);
if (t.Bytes(Encoding.UTF8).Length <= (bytes - 4)) break;
}
t = t + " ...";
}
}
return t;
}
/// <summary>获取表名。</summary>
protected static string Table<T>() => Table(typeof(T));

92
Apewer.Source/Source/SqlClient.cs

@ -1,4 +1,4 @@
/* 2021.11.07 */
/* 2021.12.01 */
using Apewer;
using System;
@ -9,6 +9,7 @@ using System.Text;
using static Apewer.Source.SourceUtility;
using System.Data.SqlClient;
using System.IO;
#if NETFRAMEWORK
using System.Data.Sql;
@ -113,6 +114,24 @@ namespace Apewer.Source
}
}
/// <summary>改变</summary>
/// <param name="store"></param>
/// <returns></returns>
public string Change(string store)
{
if (store.IsEmpty()) return "未指定数据名称。";
var connect = Connect();
if (connect.NotEmpty()) return connect;
try
{
_db.ChangeDatabase(store);
return null;
}
catch (Exception ex) { return ex.Message(); }
}
/// <summary>关闭连接,并释放对象所占用的系统资源。</summary>
public void Close()
{
@ -249,10 +268,13 @@ namespace Apewer.Source
}
/// <summary>执行。</summary>
public IExecute Execute(string sql) => Execute(sql, null);
public IExecute Execute(string sql) => Execute(sql, null, true);
/// <summary>执行单条 Transact-SQL 语句,并加入参数。</summary>
public IExecute Execute(string sql, IEnumerable<IDataParameter> parameters)
public IExecute Execute(string sql, IEnumerable<IDataParameter> parameters) => Execute(sql, parameters, true);
/// <summary>执行单条 Transact-SQL 语句,并加入参数。</summary>
IExecute Execute(string sql, IEnumerable<IDataParameter> parameters, bool requireTransaction)
{
if (TextUtility.IsBlank(sql)) return Example.InvalidExecuteStatement;
@ -260,13 +282,13 @@ namespace Apewer.Source
if (connected.NotEmpty()) return new Execute(false, connected);
var inTransaction = _transaction != null;
if (!inTransaction) Begin();
if (requireTransaction && !inTransaction) Begin();
try
{
using (var command = new SqlCommand())
{
command.Connection = _db;
command.Transaction = (SqlTransaction)_transaction;
if (requireTransaction) command.Transaction = (SqlTransaction)_transaction;
command.CommandTimeout = _timeout.Execute;
command.CommandText = sql;
if (parameters != null)
@ -277,14 +299,14 @@ namespace Apewer.Source
}
}
var rows = command.ExecuteNonQuery();
if (!inTransaction) Commit(); // todo 此处应该检查事务提交产生的错误。
if (requireTransaction && !inTransaction) Commit(); // todo 此处应该检查事务提交产生的错误。
return new Execute(true, rows);
}
}
catch (Exception exception)
{
Logger.Error(nameof(SqlClient), "Execute", exception, sql);
if (!inTransaction) Rollback();
if (requireTransaction && !inTransaction) Rollback();
return new Execute(exception);
}
}
@ -355,6 +377,62 @@ namespace Apewer.Source
return list.ToArray();
}
/// <summary>创建数据库,返回错误信息。</summary>
/// <param name="storeName">数据库名称。</param>
/// <returns>成功时候返回 NULL 值,失败时返回错误信息。</returns>
public string CreateStore(string storeName)
{
var store = storeName.Escape().ToTrim();
if (store.IsEmpty()) return "创建失败:未指定数据库名称。";
if (ConnectionString.IsEmpty()) return "创建失败:未指定数据库连接方式。";
using (var source = new SqlClient(ConnectionString))
{
var connect = source.Connect();
if (connect.NotEmpty()) return "创建失败:" + connect;
var schema = source.SimpleCell("select default_schema_name from sys.database_principals where type = 'S' and name=user_name()");
if (schema.IsEmpty()) return "创建失败:无法获取默认模式名称。";
var refPath = source.SimpleCell(@"select f.physical_name path from sys.filegroups g left join sys.database_files f on f.data_space_id = g.data_space_id where g.name = 'PRIMARY' and g.type = 'FG' and g.is_default = 1 and g.filegroup_guid is null");
if (refPath.IsEmpty()) return "创建失败:无法获取文件路径。";
var dir = Path.GetDirectoryName(refPath);
var mdfPath = Path.Combine(dir, store) + ".mdf";
var ldfPath = Path.Combine(dir, store) + "_log.ldf";
// 创建库。
var sql1 = $@"
CREATE DATABASE [{store}]
ON PRIMARY
(
NAME = N'{store}',
FILENAME = N'{mdfPath}',
SIZE = 8192KB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 4MB
)
LOG ON
(
NAME = N'{store}_log',
FILENAME = N'{ldfPath}',
SIZE = 8MB,
MAXSIZE = 1024MB,
FILEGROWTH = 4MB
)
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";
source.Execute(sql2, null, false);
return null;
}
}
static string XType(int xtype)
{
switch (xtype)

2
Apewer/Apewer.props

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

6
Apewer/NetworkUtility.cs

@ -383,7 +383,7 @@ namespace Apewer
#region Port
private static int[] ListActivePort(IPEndPoint[] endpoints)
private static int[] ActivePorts(IPEndPoint[] endpoints)
{
var list = new List<int>(endpoints.Length);
foreach (var endpoint in endpoints)
@ -398,10 +398,10 @@ namespace Apewer
}
/// <summary>列出活动的 TCP 端口。</summary>
public static int[] ListActiveTcpPort() => ListActivePort(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
public static int[] ActiveTcpPorts() => ActivePorts(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
/// <summary>列出活动的 UDP 端口。</summary>
public static int[] ListActiveUdpPort() => ListActivePort(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners());
public static int[] ActiveUdpPorts() => ActivePorts(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners());
#endregion

36
Apewer/Source/Query.cs

@ -303,42 +303,6 @@ 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); } }
/// <summary>简单查询:取结果中第 0 列所有单元格的文本形式,可指定查询后关闭服务器连接,返回结果中不包含无效文本。</summary>
public static string[] SimpleColumn(IDbAdo database, string statement, bool dispose = false)
{
if (database == null) return new string[0];
var ab = new ArrayBuilder<string>();
using (var query = database.Query(statement))
{
var rows = query.Rows;
if (rows > 0)
{
var added = 0;
for (int i = 0; i < rows; i++)
{
var cell = Trim(query.Text(i));
if (string.IsNullOrEmpty(cell)) continue;
ab.Add(cell);
added++;
}
}
}
if (dispose) RuntimeUtility.Dispose(database);
return ab.Export();
}
/// <summary>简单查询:取结果中第 0 行、第 0 列单元格中的文本,可指定查询后关闭服务器连接。</summary>
public static string SimpleCell(IDbAdo database, string statement, bool dispose = false)
{
if (database == null) return "";
var query = database.Query(statement);
var cell = Trim(Query.Text(query.Value()));
query.Dispose();
if (dispose) RuntimeUtility.Dispose(database);
return cell;
}
#endregion
#region Extension

78
Apewer/Source/SourceUtility.cs

@ -436,6 +436,84 @@ namespace Apewer.Source
#endregion
#region DbClient
/// <summary>简单查询:取结果中第 0 列所有单元格的文本形式,可指定查询后关闭服务器连接,返回结果中不包含无效文本。</summary>
/// <param name="source">数据库客户端。</param>
/// <param name="sql">用于查询的 SQL 语句。</param>
/// <param name="close">查询后,关闭数据库链接。</param>
public static string[] SimpleColumn(this IDbAdo source, string sql, bool close = false)
{
if (source == null) return new string[0];
var ab = new ArrayBuilder<string>();
using (var query = source.Query(sql))
{
var rows = query.Rows;
if (rows > 0)
{
var added = 0;
for (int i = 0; i < rows; i++)
{
var cell = TextUtility.Trim(query.Text(i));
if (string.IsNullOrEmpty(cell)) continue;
ab.Add(cell);
added++;
}
}
}
if (close) RuntimeUtility.Dispose(source);
return ab.Export();
}
/// <summary>简单查询:取结果中第 0 行、第 0 列单元格中的文本,可指定查询后关闭服务器连接。</summary>
/// <param name="source">数据库客户端。</param>
/// <param name="sql">用于查询的 SQL 语句。</param>
/// <param name="close">查询后,关闭数据库链接。</param>
public static string SimpleCell(this IDbAdo source, string sql, bool close = false)
{
if (source == null) return null;
var value = null as string;
using (var query = source.Query(sql)) value = TextUtility.Trim(query.Text());
if (close) RuntimeUtility.Dispose(source);
return value;
}
#endregion
#region SQL
/// <summary>对文本转义,符合 SQL 安全性。可根据字段类型限制 UTF-8 字节数,默认为 0 时不限制字节数。</summary>
public static string Escape(this string text, int bytes = 0)
{
if (text.IsEmpty()) return "";
var t = text ?? "";
t = t.Replace("\\", "\\\\");
t = t.Replace("'", "\\'");
t = t.Replace("\n", "\\n");
t = t.Replace("\r", "\\r");
t = t.Replace("\b", "\\b");
t = t.Replace("\t", "\\t");
t = t.Replace("\f", "\\f");
if (bytes > 5)
{
if (t.Bytes(Encoding.UTF8).Length > bytes)
{
while (true)
{
t = t.Substring(0, t.Length - 1);
if (t.Bytes(Encoding.UTF8).Length <= (bytes - 4)) break;
}
t = t + " ...";
}
}
return t;
}
#endregion
}
}

9
ChangeLog.md

@ -1,6 +1,15 @@

### 最新提交
### 6.5.8
- Source:SqlClient 新增 CreateStore 方法,支持创建数据库。
### 6.5.7
- ArrayBuilder:增加 Contains 方法和 IndexOf 方法;
- NetworkUtility:ListActivePort 返回值改为数组;
- RuntimeUtility:StartThread 默认使用前台线程;
- Source:OrmHelper 重命名为 SourceUtility。
### 6.5.6
- Global:增加 IsNull 和 NotNull 扩展方法;
- ArrayBuilder:添加了 Add 重载方法;

Loading…
Cancel
Save