mirror of
https://github.com/FalconWu2017/Falcon.StoredProcedureRunner.git
synced 2024-11-23 05:29:37 +08:00
发布2.1版本,支持Oracle和SqlServer
This commit is contained in:
parent
2bcbeb4dae
commit
177d648979
|
@ -2,3 +2,10 @@
|
|||
|
||||
# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
dotnet_diagnostic.CS8618.severity = none
|
||||
|
||||
# CS1591: 缺少对公共可见类型或成员的 XML 注释
|
||||
dotnet_diagnostic.CS1591.severity = none
|
||||
|
||||
[*.{cs,vb}]
|
||||
dotnet_style_qualification_for_property=true:suggestion
|
||||
dotnet_style_qualification_for_method=false:suggestion
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示调用时候忽略此属性
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义存储过程参数方向。默认Input
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义名称
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义存储过程参数类型
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public class FalconSPPrarmTypeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数名
|
||||
/// </summary>
|
||||
public FalconSPDbType PType { get; set; }
|
||||
/// <summary>
|
||||
/// 数据长度
|
||||
/// </summary>
|
||||
public int? Size { get; set; }
|
||||
/// <summary>
|
||||
/// 定于存储过程参数名称
|
||||
/// </summary>
|
||||
/// <param name="pDbType">参数类型.DbType</param>
|
||||
/// <param name="size">类型长度</param>
|
||||
public FalconSPPrarmTypeAttribute(FalconSPDbType pDbType, int size)
|
||||
{
|
||||
this.PType = pDbType;
|
||||
this.Size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定于存储过程参数名称
|
||||
/// </summary>
|
||||
/// <param name="pDbType">参数类型.DbType</param>
|
||||
public FalconSPPrarmTypeAttribute(FalconSPDbType pDbType) {
|
||||
this.PType = pDbType;
|
||||
this.Size = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义存储过程名称
|
|
@ -1,12 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义存储过程返回值类型
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class,AllowMultiple = false,Inherited = false)]
|
||||
public class FalconSPReturnTypeAttribute:Attribute
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public class FalconSPReturnTypeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回的数据类型
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义存储过程返回临时表名称。主要应用与oracle数据库通过临时表返回结果。
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public class FalconSPTempTableAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 存储返回临时表名称
|
||||
/// </summary>
|
||||
public string TableName { get; set; }
|
||||
/// <summary>
|
||||
/// 定义存储返回临时表名称
|
||||
/// </summary>
|
||||
/// <param name="name">临时表名称</param>
|
||||
public FalconSPTempTableAttribute(string name) => TableName=name;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置返回对象值时候发生异常
|
||||
/// 不支持的数据库类型
|
||||
/// </summary>
|
||||
public class DatabaseNotSupportedException : Exception
|
||||
{
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFrameworks>net5.0</TargetFrameworks>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Version>2.0.0</Version>
|
||||
<Version>2.1.0</Version>
|
||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||
<PackageProjectUrl>https://github.com/FalconWu2017/Falcon.StoredProcedureRunner</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/FalconWu2017/Falcon.StoredProcedureRunner</RepositoryUrl>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
/// </summary>
|
||||
public enum FalconSPDbType
|
||||
{
|
||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
//
|
||||
// 摘要:
|
||||
// System.Int64. A 64-bit signed integer.
|
||||
|
@ -201,7 +202,6 @@
|
|||
OracleBoolean = 134,
|
||||
OracleJson = 135
|
||||
|
||||
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义存储过程参数类型
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public class FalconSPPrarmTypeAttribute:Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数名
|
||||
/// </summary>
|
||||
public FalconSPDbType PType { get; set; }
|
||||
/// <summary>
|
||||
/// 定于存储过程参数名称
|
||||
/// </summary>
|
||||
/// <param name="pDbType">参数类型.DbType</param>
|
||||
public FalconSPPrarmTypeAttribute(FalconSPDbType pDbType) { this.PType = pDbType; }
|
||||
}
|
||||
}
|
7
src/Falcon.StoredProcedureRunner/IOracleRunner.cs
Normal file
7
src/Falcon.StoredProcedureRunner/IOracleRunner.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 面向Oracle的执行器
|
||||
/// </summary>
|
||||
public interface IOracleRunner : IRunner { }
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace Falcon.StoredProcedureRunner
|
|||
/// <typeparam name="TPrarmType">参数类型</typeparam>
|
||||
/// <param name="db">数据上下文</param>
|
||||
/// <param name="data">参数数据</param>
|
||||
int Execute<TPrarmType>(DbContext db,TPrarmType data);
|
||||
int Execute<TPrarmType>(DbContext db, TPrarmType data);
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库上下文执行存储过程,并返回查询结果
|
||||
|
@ -25,7 +25,7 @@ namespace Falcon.StoredProcedureRunner
|
|||
/// <param name="returnType">返回结果项类型</param>
|
||||
/// <param name="data">执行参数</param>
|
||||
/// <returns>查询结果枚举</returns>
|
||||
IEnumerable<object> Run(DbContext db,Type prarmType,Type returnType ,object data) ;
|
||||
IEnumerable<object> Run(DbContext db, Type prarmType, Type returnType, object data);
|
||||
|
||||
/// <summary>
|
||||
/// (存在sql注入风险)执行Sql语句,并将数据库返回结果以json数据对象返回。
|
||||
|
@ -33,6 +33,6 @@ namespace Falcon.StoredProcedureRunner
|
|||
/// <param name="db">数据上下文</param>
|
||||
/// <param name="sql">要执行的sql语句</param>
|
||||
/// <returns>数据库返回值json格式</returns>
|
||||
string RunRaw(DbContext db,string sql);
|
||||
string RunRaw(DbContext db, string sql);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Falcon.StoredProcedureRunner.Attributes;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
|
@ -12,7 +13,8 @@ namespace Falcon.StoredProcedureRunner
|
|||
/// </summary>
|
||||
/// <param name="services">注册服务集合</param>
|
||||
/// <returns>服务集合</returns>
|
||||
public static IServiceCollection UseFalconSPRunner(this IServiceCollection services) {
|
||||
public static IServiceCollection UseFalconSPRunner(this IServiceCollection services)
|
||||
{
|
||||
return services.AddFalconSPRunner();
|
||||
}
|
||||
|
||||
|
@ -21,8 +23,12 @@ namespace Falcon.StoredProcedureRunner
|
|||
/// </summary>
|
||||
/// <param name="services">注册服务集合</param>
|
||||
/// <returns>服务集合</returns>
|
||||
public static IServiceCollection AddFalconSPRunner(this IServiceCollection services) {
|
||||
return services.AddSingleton<IRunner,Runner>();
|
||||
public static IServiceCollection AddFalconSPRunner(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IRunner, Runner>();
|
||||
services.AddSingleton<IOracleRunner, OracleRunner>();
|
||||
services.AddSingleton<ISqlServerRunner, SqlServerRunner>();
|
||||
return services;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
7
src/Falcon.StoredProcedureRunner/ISqlServerRunner.cs
Normal file
7
src/Falcon.StoredProcedureRunner/ISqlServerRunner.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 面向SqlServer的执行器
|
||||
/// </summary>
|
||||
public interface ISqlServerRunner : IRunner { }
|
||||
}
|
124
src/Falcon.StoredProcedureRunner/OracleRunner.cs
Normal file
124
src/Falcon.StoredProcedureRunner/OracleRunner.cs
Normal file
|
@ -0,0 +1,124 @@
|
|||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Oracle.ManagedDataAccess.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Transactions;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 面向Oracle的执行器
|
||||
/// </summary>
|
||||
public class OracleRunner : RunnerBase, IOracleRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行参数
|
||||
/// </summary>
|
||||
public OracleRunnerOptions Options { get; set; }
|
||||
/// <summary>
|
||||
/// 通过提供构造选项构造Oracle执行器
|
||||
/// </summary>
|
||||
/// <param name="option">选项</param>
|
||||
public OracleRunner(IOptions<OracleRunnerOptions> option = null)
|
||||
{
|
||||
this.Options = option?.Value ?? new OracleRunnerOptions();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建存储过程参数
|
||||
/// </summary>
|
||||
protected override IDataParameter CreateDbParameter(string name, object val, int? type, int? size)
|
||||
{
|
||||
DbParameter par =
|
||||
type.HasValue && size.HasValue ? new OracleParameter(name, (OracleDbType)type, size.Value) :
|
||||
type.HasValue && !size.HasValue ? new OracleParameter(name, (OracleDbType)type) :
|
||||
!type.HasValue && !size.HasValue ? new OracleParameter(name, val) :
|
||||
null;
|
||||
par.Value = val;
|
||||
return par as IDataParameter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表是否存在
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="tableName">表名称</param>
|
||||
/// <returns>存在True,不存在False</returns>
|
||||
protected override bool IsTableExists(DbContext db, string tableName)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Oracle数据库链接
|
||||
/// </summary>
|
||||
protected override DbConnection GetDbConnection(DbContext context)
|
||||
{
|
||||
return context.Database.GetDbConnection() as OracleConnection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库前缀
|
||||
/// </summary>
|
||||
/// <returns>前缀</returns>
|
||||
protected override string GetParamProfix()
|
||||
{
|
||||
return ":";
|
||||
}
|
||||
|
||||
public override IEnumerable<object> Run(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
return this.Options.ReturnModel switch
|
||||
{
|
||||
ReturnModel.Return => RunByReturn(db, prarmType, returnType, data),
|
||||
ReturnModel.TempTable => RunByTempTable(db, prarmType, returnType, data),
|
||||
_ => throw new NotSupportedException(),
|
||||
};
|
||||
}
|
||||
|
||||
protected IEnumerable<object> RunByReturn(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
var pm = GetProcuderName(prarmType);
|
||||
var paras = getParams(prarmType, data).ToArray();
|
||||
DataSet ds = new();
|
||||
var conn = db.Database.GetDbConnection() as OracleConnection;
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.CommandText = pm;
|
||||
cmd.Parameters.AddRange(paras);
|
||||
var da = new OracleDataAdapter(cmd);
|
||||
da.Fill(ds);
|
||||
cmd.Parameters.Clear();
|
||||
return DataSetToIEnumerable(ds, returnType);
|
||||
}
|
||||
|
||||
protected IEnumerable<object> RunByTempTable(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
var pm = GetProcuderName(prarmType);
|
||||
var paras = getParams(prarmType, data).ToArray();
|
||||
var tempTable = GetTempTableName(returnType);
|
||||
using TransactionScope tran = new(TransactionScopeOption.Required);
|
||||
using var cmd = db.Database.GetDbConnection().CreateCommand() as OracleCommand;
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.CommandText = pm;
|
||||
cmd.Parameters.AddRange(paras);
|
||||
//cmd.BindByName = true;
|
||||
db.Database.GetDbConnection().Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
cmd.Parameters.Clear();
|
||||
cmd.CommandText= $"select * from {tempTable}";
|
||||
cmd.CommandType = CommandType.Text;
|
||||
var da = new OracleDataAdapter(cmd);
|
||||
DataSet ds = new();
|
||||
da.Fill(ds);
|
||||
tran.Complete();
|
||||
return DataSetToIEnumerable(ds, returnType);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
13
src/Falcon.StoredProcedureRunner/OracleRunnerOptions.cs
Normal file
13
src/Falcon.StoredProcedureRunner/OracleRunnerOptions.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// Oracle执行配置
|
||||
/// </summary>
|
||||
public class OracleRunnerOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取数据返回方式 DbReader 1或TempTable 2
|
||||
/// </summary>
|
||||
public ReturnModel ReturnModel { get; set; } = ReturnModel.TempTable;
|
||||
}
|
||||
}
|
17
src/Falcon.StoredProcedureRunner/ReturnModel.cs
Normal file
17
src/Falcon.StoredProcedureRunner/ReturnModel.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取返回值方式
|
||||
/// </summary>
|
||||
public enum ReturnModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过存储过程返回值获取数据
|
||||
/// </summary>
|
||||
Return = 1,
|
||||
/// <summary>
|
||||
/// 通过临时表表获取数据
|
||||
/// </summary>
|
||||
TempTable = 2
|
||||
}
|
||||
}
|
|
@ -1,360 +1,54 @@
|
|||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Oracle.ManagedDataAccess.Client;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 存储过程执行
|
||||
/// 通用存储过程执行器
|
||||
/// </summary>
|
||||
public partial class Runner : IRunner
|
||||
public class Runner : IRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行无返回值的存储过程
|
||||
/// 注册的所有服务
|
||||
/// </summary>
|
||||
/// <typeparam name="TPrarmType">参数类型</typeparam>
|
||||
/// <param name="db">数据上下文</param>
|
||||
/// <param name="data">参数数据</param>
|
||||
public IServiceProvider Service { get; }
|
||||
/// <summary>
|
||||
/// 通过注册的服务实例化执行器
|
||||
/// </summary>
|
||||
/// <param name="service">服务集合</param>
|
||||
public Runner(IServiceProvider service)
|
||||
{
|
||||
Service = service;
|
||||
}
|
||||
|
||||
public int Execute<TPrarmType>(DbContext db, TPrarmType data)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
//var parms = getParams(db, typeof(TPrarmType), data).ToArray();
|
||||
//var pName = getProcuderName<TPrarmType>();
|
||||
//var conn = db.Database.GetDbConnection();
|
||||
|
||||
|
||||
//var paramStr = getParamStr(typeof(TPrarmType), data);
|
||||
//var str = $"exec {pName} {paramStr}";
|
||||
//return db.Database.ExecuteSqlRaw(str, parms);
|
||||
return GetRunner(db).Execute<TPrarmType>(db, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库上下文执行存储过程,并返回查询结果
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="prarmType">参数类型</param>
|
||||
/// <param name="returnType">返回值类型</param>
|
||||
/// <param name="data">存储过程参数</param>
|
||||
/// <returns>查询结果枚举</returns>
|
||||
public IEnumerable<object> Run(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
return RunByReader(db, prarmType, returnType, data);
|
||||
return GetRunner(db).Run(db, prarmType, returnType, data);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库上下文执行存储过程,并返回查询结果
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="prarmType">参数类型</param>
|
||||
/// <param name="returnType">返回值类型</param>
|
||||
/// <param name="data">存储过程参数</param>
|
||||
/// <returns>查询结果枚举</returns>
|
||||
public IEnumerable<object> RunByReader(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
var pm = getProcuderName(prarmType);
|
||||
var paras = getParams(db, prarmType, data).ToArray();
|
||||
var connection = db.Database.GetDbConnection();
|
||||
using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = pm;
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.Parameters.AddRange(paras);
|
||||
connection.Open();
|
||||
using var dr = cmd.ExecuteReader();
|
||||
var columnSchema = dr.GetColumnSchema();
|
||||
var result = new List<object>();
|
||||
if (!dr.CanGetColumnSchema())
|
||||
return result;
|
||||
int rowId = 0;
|
||||
while (dr.Read())
|
||||
{
|
||||
var item = returnType.Assembly.CreateInstance(returnType.FullName);
|
||||
for (var i = 0; i < columnSchema.Count; i++)
|
||||
{
|
||||
var name = dr.GetName(i);
|
||||
var value = dr.IsDBNull(i) ? null : dr.GetValue(i);
|
||||
var pi = getProperty(returnType, name);
|
||||
if (pi == null || !pi.CanWrite)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
pi.SetValue(item, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ReturnDataSetValueException(rowId, name, pi, value, ex);
|
||||
}
|
||||
}
|
||||
result.Add(item);
|
||||
rowId++;
|
||||
}
|
||||
connection.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库上下文执行存储过程,并返回查询结果
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="prarmType">参数类型</param>
|
||||
/// <param name="returnType">返回值类型</param>
|
||||
/// <param name="data">存储过程参数</param>
|
||||
/// <returns>查询结果枚举</returns>
|
||||
public IEnumerable<object> RunByDbset(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
var result = new List<object>();
|
||||
var pm = getProcuderName(prarmType);
|
||||
var paras = getParams(db, prarmType, data).ToArray();
|
||||
DbConnection connection = db.Database.GetDbConnection();
|
||||
DataSet ds = new DataSet();
|
||||
if (db.Database.IsOracle())
|
||||
{
|
||||
var conn = db.Database.GetDbConnection() as OracleConnection;
|
||||
using var cmd = new OracleCommand(pm, conn);
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.Parameters.AddRange(paras);
|
||||
var da = new OracleDataAdapter(cmd);
|
||||
da.Fill(ds);
|
||||
}
|
||||
else if (db.Database.IsSqlServer())
|
||||
{
|
||||
var oracleConn = db.Database.GetDbConnection() as SqlConnection;
|
||||
using var oracleCmd = new SqlCommand(pm, oracleConn);
|
||||
oracleCmd.CommandType = CommandType.StoredProcedure;
|
||||
oracleCmd.Parameters.AddRange(paras);
|
||||
var da = new SqlDataAdapter(oracleCmd);
|
||||
da.Fill(ds);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DatabaseNotSupportedException();
|
||||
}
|
||||
var rows = ds.Tables[0].Rows;
|
||||
var cols = ds.Tables[0].Columns;
|
||||
for (int i = 0; i < rows.Count; i++)
|
||||
{
|
||||
var item = returnType.Assembly.CreateInstance(returnType.FullName);
|
||||
var row = rows[i];
|
||||
for (int y = 0; y < cols.Count; y++)
|
||||
{
|
||||
var name = cols[y].ColumnName;
|
||||
var val = row[y] is DBNull ? null : row[y];
|
||||
var pi = getProperty(returnType, name);
|
||||
if (pi == null || !pi.CanWrite)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
pi.SetValue(item, val);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ReturnDataSetValueException(i, name, pi, val, ex);
|
||||
}
|
||||
}
|
||||
result.Add(item);
|
||||
}
|
||||
connection.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// (存在sql注入风险)执行Sql语句,并将数据库返回结果以json数据对象返回。
|
||||
/// </summary>
|
||||
/// <param name="db">数据上下文</param>
|
||||
/// <param name="sql">要执行的sql语句</param>
|
||||
/// <returns>数据库返回值json格式</returns>
|
||||
public string RunRaw(DbContext db, string sql)
|
||||
{
|
||||
var connection = db.Database.GetDbConnection();
|
||||
using (var cmd = connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = System.Data.CommandType.Text;
|
||||
connection.Open();
|
||||
var dr = cmd.ExecuteReader();
|
||||
var result = new StringBuilder();
|
||||
if (!dr.CanGetColumnSchema())
|
||||
return "";
|
||||
while (dr.Read())
|
||||
{
|
||||
var item = new StringBuilder();
|
||||
var columnSchema = dr.GetColumnSchema();
|
||||
for (var i = 0; i < columnSchema.Count; i++)
|
||||
{
|
||||
var name = dr.GetName(i);
|
||||
var value = dr.IsDBNull(i) ? null : dr.GetValue(i);
|
||||
item.Append($"\"{name}\":\"{value}\",");
|
||||
return GetRunner(db).RunRaw(db, sql);
|
||||
}
|
||||
result.Append($"{{{item.ToString().TrimEnd(',')}}},");
|
||||
}
|
||||
connection.Close();
|
||||
return "[" + result.ToString().TrimEnd(',') + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内部保护方法
|
||||
/// </summary>
|
||||
public partial class Runner
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取存储过程名
|
||||
/// </summary>
|
||||
/// <param name="pramType">参数类型</param>
|
||||
private static string getProcuderName(Type pramType)
|
||||
{
|
||||
var attr = pramType.GetCustomAttribute<FalconSPProcuderNameAttribute>();
|
||||
return attr?.ProcuderName ?? pramType.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程参数枚举
|
||||
/// </summary>
|
||||
///<param name="type">数据的类型</param>
|
||||
/// <param name="data">参数实例</param>
|
||||
private static IEnumerable<IDataParameter> getParams(DbContext db, Type type, object data)
|
||||
{
|
||||
if (data == null)
|
||||
yield break;
|
||||
var fixC =
|
||||
db.Database.IsOracle() ? ":" :
|
||||
db.Database.IsSqlServer() ? "@" :
|
||||
throw new DatabaseNotSupportedException();
|
||||
|
||||
foreach (var p in type.GetProperties())
|
||||
{
|
||||
if (!p.CanRead || isIgnoreProp(p))
|
||||
continue;
|
||||
var name = getPrarmName(p, fixC);
|
||||
var val = p.GetValue(data);
|
||||
var pt = getPrarmType(p);
|
||||
var para = CreateDbParameter(db, name, val, pt);
|
||||
para.Direction = GetParaDirection(p);
|
||||
yield return para;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程参数类型
|
||||
/// </summary>
|
||||
/// <param name="p">对应的属性</param>
|
||||
private static int? getPrarmType(PropertyInfo p)
|
||||
{
|
||||
var np = p.GetCustomAttribute<FalconSPPrarmTypeAttribute>();
|
||||
if (np != null && np is FalconSPPrarmTypeAttribute na)
|
||||
{
|
||||
return (int)np.PType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建存储过程参数
|
||||
/// 获取特定类型的数据库runnner
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="name">参数名称</param>
|
||||
/// <param name="val">参数值</param>
|
||||
/// <returns>参数</returns>
|
||||
private static IDataParameter CreateDbParameter(DbContext db, string name, object val, int? type)
|
||||
{
|
||||
var dbf = db.Database;
|
||||
if (type.HasValue)
|
||||
{
|
||||
IDataParameter pra =
|
||||
dbf.IsOracle() ? new OracleParameter(name, (OracleDbType)type) :
|
||||
dbf.IsSqlServer() ? new SqlParameter(name, (SqlDbType)type) :
|
||||
throw new DatabaseNotSupportedException();
|
||||
pra.Value = val;
|
||||
return pra;
|
||||
}
|
||||
else
|
||||
/// <returns>特定类型的执行器</returns>
|
||||
/// <exception cref="DatabaseNotSupportedException"></exception>
|
||||
protected IRunner GetRunner(DbContext db)
|
||||
{
|
||||
return
|
||||
dbf.IsSqlServer() ? new SqlParameter(name, val) :
|
||||
dbf.IsOracle() ? new OracleParameter(name, val) :
|
||||
db.Database.IsOracle() ? Service.GetService<IOracleRunner>() :
|
||||
db.Database.IsSqlServer() ? Service.GetService<IOracleRunner>() :
|
||||
throw new DatabaseNotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取参数的方向。默认Input
|
||||
/// </summary>
|
||||
/// <param name="p">参数映射属性</param>
|
||||
/// <returns>方向或null</returns>
|
||||
private static ParameterDirection GetParaDirection(PropertyInfo p)
|
||||
{
|
||||
var attr = p.GetCustomAttribute<FalconSPPrarmDirectionAttribute>();
|
||||
return attr == null ? ParameterDirection.Input : attr.Direction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否忽略属性
|
||||
/// </summary>
|
||||
/// <param name="p">要检查的属性</param>
|
||||
private static bool isIgnoreProp(PropertyInfo p)
|
||||
{
|
||||
return p.GetCustomAttribute<FalconSPIgnoreAttribute>(true) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程参数名称
|
||||
/// </summary>
|
||||
/// <param name="p">对应的属性</param>
|
||||
private static string getPrarmName(PropertyInfo p, string prefixChar)
|
||||
{
|
||||
var np = p.GetCustomAttribute<FalconSPPrarmNameAttribute>(true);
|
||||
if (np != null && np is FalconSPPrarmNameAttribute na)
|
||||
{
|
||||
var name = na.Name;
|
||||
return name.StartsWith(prefixChar) ? name : prefixChar + name;
|
||||
}
|
||||
return prefixChar + p.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 忽略大小写获取类型的属性
|
||||
/// </summary>
|
||||
/// <param name="t">类型</param>
|
||||
/// <param name="name">属性名称</param>
|
||||
/// <returns>属性</returns>
|
||||
private static PropertyInfo getProperty(Type t, string name)
|
||||
{
|
||||
foreach (var item in t.GetProperties())
|
||||
{
|
||||
if (item.Name.ToLower() == name.ToLower())
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成存储过程参数字符串
|
||||
/// </summary>
|
||||
/// <param name="type">参数类型</param>
|
||||
/// <param name="data">参数对象</param>
|
||||
/// <returns>一个参数字符串。比如@p2=@p4,@p1=@p3</returns>
|
||||
//private static string getParamStr(Type type,object data) {
|
||||
// var paras = getParams(type,data).ToArray();
|
||||
// var result = " ";
|
||||
// for(int i = 0;i < paras.Count();i++) {
|
||||
// result += $"{paras[i].ParameterName}={{{i}}},";
|
||||
// }
|
||||
// return result.TrimEnd(',');
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
314
src/Falcon.StoredProcedureRunner/RunnerBase.cs
Normal file
314
src/Falcon.StoredProcedureRunner/RunnerBase.cs
Normal file
|
@ -0,0 +1,314 @@
|
|||
using Falcon.StoredProcedureRunner.Attributes;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oracle.ManagedDataAccess.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 存储过程执行
|
||||
/// </summary>
|
||||
public abstract class RunnerBase : IRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行无返回值的存储过程
|
||||
/// </summary>
|
||||
/// <typeparam name="TPrarmType">参数类型</typeparam>
|
||||
/// <param name="db">数据上下文</param>
|
||||
/// <param name="data">参数数据</param>
|
||||
public int Execute<TPrarmType>(DbContext db, TPrarmType data)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
//var parms = getParams(db, typeof(TPrarmType), data).ToArray();
|
||||
//var pName = getProcuderName<TPrarmType>();
|
||||
//var conn = db.Database.GetDbConnection();
|
||||
|
||||
|
||||
//var paramStr = getParamStr(typeof(TPrarmType), data);
|
||||
//var str = $"exec {pName} {paramStr}";
|
||||
//return db.Database.ExecuteSqlRaw(str, parms);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库上下文执行存储过程,并返回查询结果
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="prarmType">参数类型</param>
|
||||
/// <param name="returnType">返回值类型</param>
|
||||
/// <param name="data">存储过程参数</param>
|
||||
/// <returns>查询结果枚举</returns>
|
||||
public abstract IEnumerable<object> Run(DbContext db, Type prarmType, Type returnType, object data);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库上下文执行存储过程,并返回查询结果
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="prarmType">参数类型</param>
|
||||
/// <param name="returnType">返回值类型</param>
|
||||
/// <param name="data">存储过程参数</param>
|
||||
/// <returns>查询结果枚举</returns>
|
||||
protected virtual IEnumerable<object> RunByReader(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
var pm = GetProcuderName(prarmType);
|
||||
var paras = getParams( prarmType, data).ToArray();
|
||||
var conn = GetDbConnection(db);
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = pm;
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.Parameters.AddRange(paras);
|
||||
conn.Open();
|
||||
using var dr = cmd.ExecuteReader();
|
||||
cmd.Parameters.Clear();
|
||||
var columnSchema = dr.GetColumnSchema();
|
||||
var result = new List<object>();
|
||||
if (!dr.CanGetColumnSchema())
|
||||
return result;
|
||||
int rowId = 0;
|
||||
while (dr.Read())
|
||||
{
|
||||
var item = returnType.Assembly.CreateInstance(returnType.FullName);
|
||||
for (var i = 0; i < columnSchema.Count; i++)
|
||||
{
|
||||
var name = dr.GetName(i);
|
||||
var value = dr.IsDBNull(i) ? null : dr.GetValue(i);
|
||||
var pi = getProperty(returnType, name);
|
||||
if (pi == null || !pi.CanWrite)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
pi.SetValue(item, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ReturnDataSetValueException(rowId, name, pi, value, ex);
|
||||
}
|
||||
}
|
||||
result.Add(item);
|
||||
rowId++;
|
||||
}
|
||||
conn.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库链接
|
||||
/// </summary>
|
||||
/// <param name="context">数据库上下文</param>
|
||||
/// <returns>数据链接</returns>
|
||||
protected abstract DbConnection GetDbConnection(DbContext context);
|
||||
|
||||
/// <summary>
|
||||
/// 将Dataset转换为IEnumerable
|
||||
/// </summary>
|
||||
/// <param name="ds">数据集</param>
|
||||
/// <param name="returnType">枚举元素类型</param>
|
||||
/// <returns>枚举类型</returns>
|
||||
/// <exception cref="ReturnDataSetValueException">数据赋值异常</exception>
|
||||
public IEnumerable<object> DataSetToIEnumerable(DataSet ds, Type returnType)
|
||||
{
|
||||
var result = new List<object>();
|
||||
var rows = ds.Tables[0].Rows;
|
||||
var cols = ds.Tables[0].Columns;
|
||||
for (int i = 0; i < rows.Count; i++)
|
||||
{
|
||||
var item = returnType.Assembly.CreateInstance(returnType.FullName);
|
||||
var row = rows[i];
|
||||
for (int y = 0; y < cols.Count; y++)
|
||||
{
|
||||
var name = cols[y].ColumnName;
|
||||
var val = row[y] is DBNull ? null : row[y];
|
||||
var pi = getProperty(returnType, name);
|
||||
if (pi == null || !pi.CanWrite)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
pi.SetValue(item, val);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ReturnDataSetValueException(i, name, pi, val, ex);
|
||||
}
|
||||
}
|
||||
result.Add(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (存在sql注入风险)执行Sql语句,并将数据库返回结果以json数据对象返回。
|
||||
/// </summary>
|
||||
/// <param name="db">数据上下文</param>
|
||||
/// <param name="sql">要执行的sql语句</param>
|
||||
/// <returns>数据库返回值json格式</returns>
|
||||
public string RunRaw(DbContext db, string sql)
|
||||
{
|
||||
var connection = db.Database.GetDbConnection();
|
||||
using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = System.Data.CommandType.Text;
|
||||
connection.Open();
|
||||
var dr = cmd.ExecuteReader();
|
||||
var result = new StringBuilder();
|
||||
if (!dr.CanGetColumnSchema())
|
||||
return "";
|
||||
while (dr.Read())
|
||||
{
|
||||
var item = new StringBuilder();
|
||||
var columnSchema = dr.GetColumnSchema();
|
||||
for (var i = 0; i < columnSchema.Count; i++)
|
||||
{
|
||||
var name = dr.GetName(i);
|
||||
var value = dr.IsDBNull(i) ? null : dr.GetValue(i);
|
||||
item.Append($"\"{name}\":\"{value}\",");
|
||||
}
|
||||
result.Append($"{{{item.ToString().TrimEnd(',')}}},");
|
||||
}
|
||||
connection.Close();
|
||||
return "[" + result.ToString().TrimEnd(',') + "]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取返回类型临时表名称
|
||||
/// </summary>
|
||||
/// <param name="returnType">返回类型</param>
|
||||
/// <returns></returns>
|
||||
protected virtual string GetTempTableName(Type returnType)
|
||||
{
|
||||
var attr = returnType.GetCustomAttribute<FalconSPTempTableAttribute>();
|
||||
return attr?.TableName ?? returnType.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程名
|
||||
/// </summary>
|
||||
/// <param name="pramType">参数类型</param>
|
||||
protected virtual string GetProcuderName(Type pramType)
|
||||
{
|
||||
var attr = pramType.GetCustomAttribute<FalconSPProcuderNameAttribute>();
|
||||
return attr?.ProcuderName ?? pramType.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程参数枚举
|
||||
/// </summary>
|
||||
///<param name="type">数据的类型</param>
|
||||
/// <param name="data">参数实例</param>
|
||||
protected virtual IEnumerable<IDataParameter> getParams(Type type, object data)
|
||||
{
|
||||
if (data == null)
|
||||
yield break;
|
||||
var fixC = GetParamProfix();
|
||||
foreach (var p in type.GetProperties())
|
||||
{
|
||||
if (!p.CanRead || IsIgnoreProp(p))
|
||||
continue;
|
||||
var name = GetPrarmName(p, fixC);
|
||||
var val = p.GetValue(data);
|
||||
var pt = getPrarmType(p);
|
||||
var para = CreateDbParameter(name, val, pt.type, pt.size);
|
||||
para.Direction = GetParaDirection(p);
|
||||
yield return para;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库参数前缀
|
||||
/// </summary>
|
||||
/// <returns>前缀字符串</returns>
|
||||
protected abstract string GetParamProfix();
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程参数类型
|
||||
/// </summary>
|
||||
/// <param name="p">对应的属性</param>
|
||||
private (int? type, int? size) getPrarmType(PropertyInfo p)
|
||||
{
|
||||
var np = p.GetCustomAttribute<FalconSPPrarmTypeAttribute>();
|
||||
if (np != null && np is FalconSPPrarmTypeAttribute na)
|
||||
{
|
||||
return ((int)np.PType, np.Size);
|
||||
}
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建存储过程参数
|
||||
/// </summary>
|
||||
/// <param name="name">参数名称</param>
|
||||
/// <param name="val">参数值</param>
|
||||
/// <param name="type">存储过程参数数据库类型</param>
|
||||
/// <param name="size">数据长度</param>
|
||||
/// <returns>参数</returns>
|
||||
protected abstract IDataParameter CreateDbParameter(string name, object val, int? type, int? size);
|
||||
|
||||
/// <summary>
|
||||
/// 获取参数的方向。默认Input
|
||||
/// </summary>
|
||||
/// <param name="p">参数映射属性</param>
|
||||
/// <returns>方向或null</returns>
|
||||
protected virtual ParameterDirection GetParaDirection(PropertyInfo p)
|
||||
{
|
||||
var attr = p.GetCustomAttribute<FalconSPPrarmDirectionAttribute>();
|
||||
return attr == null ? ParameterDirection.Input : attr.Direction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否忽略属性
|
||||
/// </summary>
|
||||
/// <param name="p">要检查的属性</param>
|
||||
protected virtual bool IsIgnoreProp(PropertyInfo p)
|
||||
{
|
||||
return p.GetCustomAttribute<FalconSPIgnoreAttribute>(true) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取存储过程参数名称
|
||||
/// </summary>
|
||||
/// <param name="p">对应的属性</param>
|
||||
/// <param name="prefixChar">存储过程参数前缀</param>
|
||||
protected virtual string GetPrarmName(PropertyInfo p, string prefixChar)
|
||||
{
|
||||
var np = p.GetCustomAttribute<FalconSPPrarmNameAttribute>(true);
|
||||
if (np != null && np is FalconSPPrarmNameAttribute na)
|
||||
{
|
||||
var name = na.Name;
|
||||
return name.StartsWith(prefixChar) ? name : prefixChar + name;
|
||||
}
|
||||
return prefixChar + p.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 忽略大小写获取类型的属性
|
||||
/// </summary>
|
||||
/// <param name="t">类型</param>
|
||||
/// <param name="name">属性名称</param>
|
||||
/// <returns>属性</returns>
|
||||
protected virtual PropertyInfo getProperty(Type t, string name)
|
||||
{
|
||||
foreach (var item in t.GetProperties())
|
||||
{
|
||||
if (item.Name.ToLower() == name.ToLower())
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表是否存在
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="tableName">表名称</param>
|
||||
/// <returns>存在True,不存在False</returns>
|
||||
protected abstract bool IsTableExists(DbContext db, string tableName);
|
||||
}
|
||||
}
|
90
src/Falcon.StoredProcedureRunner/SqlServerRunner.cs
Normal file
90
src/Falcon.StoredProcedureRunner/SqlServerRunner.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Oracle.ManagedDataAccess.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 面向SqlServer的执行器
|
||||
/// </summary>
|
||||
public class SqlServerRunner : RunnerBase, ISqlServerRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行参数
|
||||
/// </summary>
|
||||
public SqlServerRunnerOtions Options { get; set; }
|
||||
/// <summary>
|
||||
/// 通过提供构造选项构造Oracle执行器
|
||||
/// </summary>
|
||||
/// <param name="option">选项</param>
|
||||
public SqlServerRunner(IOptions<SqlServerRunnerOtions> option = null)
|
||||
{
|
||||
this.Options = option?.Value ?? new SqlServerRunnerOtions();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表是否存在
|
||||
/// </summary>
|
||||
/// <param name="db">数据库上下文</param>
|
||||
/// <param name="tableName">表名称</param>
|
||||
/// <returns>存在True,不存在False</returns>
|
||||
protected override bool IsTableExists(DbContext db, string tableName)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override IEnumerable<object> Run(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
return RunByReturn(db, prarmType, returnType, data);
|
||||
}
|
||||
|
||||
protected IEnumerable<object> RunByReturn(DbContext db, Type prarmType, Type returnType, object data)
|
||||
{
|
||||
var pm = GetProcuderName(prarmType);
|
||||
var paras = getParams(prarmType, data).ToArray();
|
||||
DbConnection connection = db.Database.GetDbConnection();
|
||||
DataSet ds = new();
|
||||
var conn = db.Database.GetDbConnection() as SqlConnection;
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.CommandText = pm;
|
||||
cmd.Parameters.AddRange(paras);
|
||||
var da = new SqlDataAdapter(cmd);
|
||||
da.Fill(ds);
|
||||
cmd.Parameters.Clear();
|
||||
return DataSetToIEnumerable(ds, returnType);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取SqlServer数据库链接
|
||||
/// </summary>
|
||||
protected override DbConnection GetDbConnection(DbContext context)
|
||||
{
|
||||
return context.Database.GetDbConnection();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取存储过程参数前缀
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override string GetParamProfix()
|
||||
{
|
||||
return "@";
|
||||
}
|
||||
|
||||
protected override IDataParameter CreateDbParameter(string name, object val, int? type, int? size)
|
||||
{
|
||||
DbParameter par =
|
||||
type.HasValue && size.HasValue ? new SqlParameter(name, (SqlDbType)type, size.Value) :
|
||||
type.HasValue && !size.HasValue ? new SqlParameter(name, (SqlDbType)type) :
|
||||
!type.HasValue && !size.HasValue ? new SqlParameter(name, val) :
|
||||
null;
|
||||
par.Value = val;
|
||||
return par as IDataParameter;
|
||||
}
|
||||
}
|
||||
}
|
10
src/Falcon.StoredProcedureRunner/SqlServerRunnerOtions.cs
Normal file
10
src/Falcon.StoredProcedureRunner/SqlServerRunnerOtions.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Falcon.StoredProcedureRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// Sqlserver执行配置
|
||||
/// </summary>
|
||||
public class SqlServerRunnerOtions
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -3,5 +3,11 @@
|
|||
"ver": "",
|
||||
"oracle": "",
|
||||
"sqlserver": ""
|
||||
},
|
||||
"OracleRunner": {
|
||||
"ReturnModel": 2
|
||||
},
|
||||
"SqlRunner": {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
|
||||
|
@ -35,4 +36,8 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Falcon\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Falcon.StoredProcedureRunner;
|
||||
using Falcon.StoredProcedureRunner.Attributes;
|
||||
using System.Data;
|
||||
|
||||
namespace Falcon.StoredProcedureRunnerTests
|
||||
|
@ -24,27 +25,24 @@ namespace Falcon.StoredProcedureRunnerTests
|
|||
/// </summary>
|
||||
public class Tjjk_Tjgh
|
||||
{
|
||||
/// <summary>
|
||||
/// 身份证号码
|
||||
/// </summary>
|
||||
public string v_sfz { get; set; }
|
||||
/// <summary>
|
||||
/// 医疗机构代码
|
||||
/// </summary>
|
||||
public string v_yljgdm { get; set; }
|
||||
/// <summary>
|
||||
/// 身份证号码
|
||||
/// </summary>
|
||||
public string v_sfz { get; set; }
|
||||
/// <summary>
|
||||
/// 挂号日期 格式yyyyMMdd
|
||||
/// </summary>
|
||||
public string v_ghrq { get; set; }
|
||||
|
||||
[FalconSPPrarmDirection(ParameterDirection.Output)]
|
||||
[FalconSPPrarmType(FalconSPDbType.OracleRefCursor)]
|
||||
public object v_data { get; set; }
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 挂号查询结果
|
||||
/// </summary>
|
||||
[FalconSPTempTable("TT_Tjjk_Tjgh")]
|
||||
public class Tjjk_TjghResult
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -3,33 +3,53 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Oracle.ManagedDataAccess.Client;
|
||||
using System.Data;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Falcon.StoredProcedureRunner.Tests
|
||||
{
|
||||
[TestClass()]
|
||||
public class RunnerTests
|
||||
{
|
||||
[TestMethod("通用测试")]
|
||||
[TestMethod("Runner创建测试")]
|
||||
public void RunTest()
|
||||
{
|
||||
OracleTest();
|
||||
System.Console.WriteLine("---------------------");
|
||||
SqlserverTest();
|
||||
var config = GetConfiguration();
|
||||
var services = CreateServiceScope(config);
|
||||
System.Console.WriteLine("数据注入完成");
|
||||
System.Console.WriteLine("sqlRunner开始测试");
|
||||
var sqlRunner = GetSqlRunner(services);
|
||||
Assert.IsNotNull(sqlRunner);
|
||||
Assert.IsNotNull(sqlRunner as ISqlServerRunner);
|
||||
Assert.IsNotNull(sqlRunner as SqlServerRunner);
|
||||
var sRunner = sqlRunner as SqlServerRunner;
|
||||
Assert.IsNotNull(sRunner.Options);
|
||||
System.Console.WriteLine("OracleRunner开始测试");
|
||||
var oracleRunner = GetOracleRunner(services);
|
||||
Assert.IsNotNull(oracleRunner);
|
||||
Assert.IsNotNull(oracleRunner as IOracleRunner);
|
||||
Assert.IsNotNull(oracleRunner as OracleRunner);
|
||||
var oRunner = oracleRunner as OracleRunner;
|
||||
Assert.IsNotNull(oRunner.Options);
|
||||
Assert.IsTrue(oRunner.Options.ReturnModel == ReturnModel.TempTable);
|
||||
|
||||
//OracleTest();
|
||||
//System.Console.WriteLine("---------------------");
|
||||
//SqlserverTest();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
|
||||
[TestMethod("Sqlserver执行测试")]
|
||||
public void SqlserverTest()
|
||||
{
|
||||
System.Console.WriteLine("SqlserverTest start!");
|
||||
var configurationBuilder = new ConfigurationBuilder();
|
||||
configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
configurationBuilder.AddUserSecrets(this.GetType().Assembly);
|
||||
var config = configurationBuilder.Build();
|
||||
var sql = config.GetSection("db:sqlserver").Value;
|
||||
var buider = new DbContextOptionsBuilder();
|
||||
var db = new DbContext(buider.UseSqlServer(sql).Options);
|
||||
IRunner runner = new Runner();
|
||||
|
||||
var config = GetConfiguration();
|
||||
var services = CreateServiceScope(config);
|
||||
var db = CreateSqlDbContext(config);
|
||||
Assert.IsNotNull(db);
|
||||
var runner = GetSqlRunner(services);
|
||||
Assert.IsNotNull(runner);
|
||||
var result = runner.Run<SqlserverModel, SqlserverModelResult>(db, new SqlserverModel
|
||||
{
|
||||
p1 = 1,
|
||||
|
@ -44,54 +64,21 @@ namespace Falcon.StoredProcedureRunner.Tests
|
|||
System.Console.WriteLine("SqlserverTest over!");
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
[TestMethod("Oracle执行测试")]
|
||||
public void OracleTest()
|
||||
{
|
||||
System.Console.WriteLine("OracleTest start!");
|
||||
var configurationBuilder = new ConfigurationBuilder();
|
||||
configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
configurationBuilder.AddUserSecrets(this.GetType().Assembly);
|
||||
var config = configurationBuilder.Build();
|
||||
var ora = config.GetSection("db:oracle").Value;
|
||||
var oraVer = config.GetSection("db:ver").Value;
|
||||
var buider = new DbContextOptionsBuilder();
|
||||
var db = new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options);
|
||||
var config = GetConfiguration();
|
||||
var services = CreateServiceScope(config);
|
||||
var db = CreateOracleDbContext(config);
|
||||
Assert.IsNotNull(db);
|
||||
var runner = GetOracleRunner(services);
|
||||
Assert.IsNotNull(runner);
|
||||
|
||||
IRunner runner = new Runner();
|
||||
var result = runner.Run<GetEmployee, GetEmployeeResult>(db, new GetEmployee
|
||||
{
|
||||
v_orgaid = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
|
||||
}).ToList();
|
||||
Assert.IsNotNull(result);
|
||||
System.Console.WriteLine("result ok");
|
||||
CollectionAssert.AllItemsAreNotNull(result);
|
||||
Assert.IsTrue(result.Count > 0);
|
||||
System.Console.WriteLine($"result count {result.Count}");
|
||||
System.Console.WriteLine("OracleTest over!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 体检接口 挂号查询测试
|
||||
/// </summary>
|
||||
[TestMethod()]
|
||||
public void Tjjk_TjghTest()
|
||||
{
|
||||
System.Console.WriteLine("OracleTest start!");
|
||||
var configurationBuilder = new ConfigurationBuilder();
|
||||
configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
configurationBuilder.AddUserSecrets(this.GetType().Assembly);
|
||||
var config = configurationBuilder.Build();
|
||||
var ora = config.GetSection("db:oracle").Value;
|
||||
var oraVer = config.GetSection("db:ver").Value;
|
||||
var buider = new DbContextOptionsBuilder();
|
||||
var db = new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options);
|
||||
|
||||
IRunner runner = new Runner();
|
||||
var result = runner.Run<Tjjk_Tjgh, Tjjk_TjghResult>(db, new Tjjk_Tjgh
|
||||
{
|
||||
v_yljgdm = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
|
||||
v_ghrq = "20211105",
|
||||
v_sfz = "610528199002165174",
|
||||
v_yljgdm = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
|
||||
}).ToList();
|
||||
Assert.IsNotNull(result);
|
||||
System.Console.WriteLine("result ok");
|
||||
|
@ -101,31 +88,142 @@ namespace Falcon.StoredProcedureRunner.Tests
|
|||
System.Console.WriteLine("OracleTest over!");
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void GetDoctorDataTest()
|
||||
[TestMethod("Oracle原始执行执行测试")]
|
||||
public void OracleRawTest()
|
||||
{
|
||||
var config = GetConfiguration();
|
||||
var services = CreateServiceScope(config);
|
||||
var db = CreateOracleDbContext(config);
|
||||
Assert.IsNotNull(db);
|
||||
var cmd = db.Database.GetDbConnection().CreateCommand() as OracleCommand;
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.CommandText = "Tjjk_Tjgh";
|
||||
var a = new OracleParameter(":v_yljgdm", OracleDbType.Char, 36)
|
||||
{
|
||||
Value = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113"
|
||||
};
|
||||
cmd.Parameters.Add(a);
|
||||
|
||||
var c = new OracleParameter(":v_sfz", OracleDbType.Varchar2, 36);
|
||||
c.Value = "610528199002165174";
|
||||
cmd.Parameters.Add(c);
|
||||
|
||||
var b = new OracleParameter(":v_ghrq", OracleDbType.Char, 8);
|
||||
b.Value = "20211105";
|
||||
cmd.Parameters.Add(b);
|
||||
db.Database.GetDbConnection().Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
cmd.CommandText = "select * from tt_tjjk_tjgh";
|
||||
cmd.CommandType = CommandType.Text;
|
||||
var da = new OracleDataAdapter(cmd);
|
||||
DataSet ds = new();
|
||||
da.Fill(ds);
|
||||
System.Console.WriteLine(ds.Tables[0].Rows.Count);
|
||||
}
|
||||
|
||||
public DbContext CreateSqlDbContext(IConfiguration config)
|
||||
{
|
||||
var ora = config.GetSection("db:sqlserver").Value;
|
||||
var buider = new DbContextOptionsBuilder();
|
||||
return new DbContext(buider.UseSqlServer(ora).Options);
|
||||
}
|
||||
|
||||
public DbContext CreateOracleDbContext(IConfiguration config)
|
||||
{
|
||||
System.Console.WriteLine("OracleTest start!");
|
||||
var configurationBuilder = new ConfigurationBuilder();
|
||||
configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
configurationBuilder.AddUserSecrets(this.GetType().Assembly);
|
||||
var config = configurationBuilder.Build();
|
||||
var ora = config.GetSection("db:oracle").Value;
|
||||
var oraVer = config.GetSection("db:ver").Value;
|
||||
var buider = new DbContextOptionsBuilder();
|
||||
var db = new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options);
|
||||
|
||||
IRunner runner = new Runner();
|
||||
var result = runner.Run<GetDoctorData, GetDoctorDataResult>(db, new GetDoctorData
|
||||
{
|
||||
v_orgaid = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
|
||||
}).ToList();
|
||||
Assert.IsNotNull(result);
|
||||
System.Console.WriteLine("result ok");
|
||||
CollectionAssert.AllItemsAreNotNull(result);
|
||||
Assert.IsTrue(result.Count > 0);
|
||||
System.Console.WriteLine($"result count {result.Count}");
|
||||
System.Console.WriteLine("OracleTest over!");
|
||||
return new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options);
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 体检接口 挂号查询测试
|
||||
///// </summary>
|
||||
//[TestMethod()]
|
||||
//public void Tjjk_TjghTest()
|
||||
//{
|
||||
// System.Console.WriteLine("OracleTest start!");
|
||||
// var configurationBuilder = new ConfigurationBuilder();
|
||||
// configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
// configurationBuilder.AddUserSecrets(this.GetType().Assembly);
|
||||
// var config = configurationBuilder.Build();
|
||||
// var ora = config.GetSection("db:oracle").Value;
|
||||
// var oraVer = config.GetSection("db:ver").Value;
|
||||
// var buider = new DbContextOptionsBuilder();
|
||||
// var db = new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options);
|
||||
|
||||
// IRunner runner = new Runner();
|
||||
// var result = runner.Run<Tjjk_Tjgh, Tjjk_TjghResult>(db, new Tjjk_Tjgh
|
||||
// {
|
||||
// v_ghrq = "20211105",
|
||||
// v_sfz = "610528199002165174",
|
||||
// v_yljgdm = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
|
||||
// }).ToList();
|
||||
// Assert.IsNotNull(result);
|
||||
// System.Console.WriteLine("result ok");
|
||||
// CollectionAssert.AllItemsAreNotNull(result);
|
||||
// Assert.IsTrue(result.Count > 0);
|
||||
// System.Console.WriteLine($"result count {result.Count}");
|
||||
// System.Console.WriteLine("OracleTest over!");
|
||||
//}
|
||||
|
||||
//[TestMethod()]
|
||||
//public void GetDoctorDataTest()
|
||||
//{
|
||||
// System.Console.WriteLine("OracleTest start!");
|
||||
// var configurationBuilder = new ConfigurationBuilder();
|
||||
// configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
// configurationBuilder.AddUserSecrets(this.GetType().Assembly);
|
||||
// var config = configurationBuilder.Build();
|
||||
// var ora = config.GetSection("db:oracle").Value;
|
||||
// var oraVer = config.GetSection("db:ver").Value;
|
||||
// var buider = new DbContextOptionsBuilder();
|
||||
// var db = new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options);
|
||||
|
||||
// IRunner runner = new Runner();
|
||||
// var result = runner.Run<GetDoctorData, GetDoctorDataResult>(db, new GetDoctorData
|
||||
// {
|
||||
// v_orgaid = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
|
||||
// }).ToList();
|
||||
// Assert.IsNotNull(result);
|
||||
// System.Console.WriteLine("result ok");
|
||||
// CollectionAssert.AllItemsAreNotNull(result);
|
||||
// Assert.IsTrue(result.Count > 0);
|
||||
// System.Console.WriteLine($"result count {result.Count}");
|
||||
// System.Console.WriteLine("OracleTest over!");
|
||||
//}
|
||||
|
||||
public static IConfiguration GetConfiguration()
|
||||
{
|
||||
var configurationBuilder = new ConfigurationBuilder();
|
||||
configurationBuilder.AddJsonFile("AppSettings.json");
|
||||
configurationBuilder.AddUserSecrets(typeof(RunnerTests).Assembly);
|
||||
return configurationBuilder.Build();
|
||||
}
|
||||
|
||||
|
||||
private IServiceScope CreateServiceScope(IConfiguration config)
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
AddOptions(config, services);
|
||||
services.AddFalconSPRunner();
|
||||
return services.BuildServiceProvider().CreateScope();
|
||||
}
|
||||
|
||||
public static void AddOptions(IConfiguration config, IServiceCollection services)
|
||||
{
|
||||
services.Configure<OracleRunnerOptions>(config.GetSection("OracleRunner"));
|
||||
services.Configure<SqlServerRunnerOtions>(config.GetSection("SqlRunner"));
|
||||
}
|
||||
|
||||
public static IRunner? GetSqlRunner(IServiceScope services)
|
||||
{
|
||||
return services.ServiceProvider.GetService<ISqlServerRunner>() as IRunner;
|
||||
}
|
||||
|
||||
public static IRunner? GetOracleRunner(IServiceScope services)
|
||||
{
|
||||
return services.ServiceProvider.GetService<IOracleRunner>() as IRunner;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Falcon.StoredProcedureRunner.Attributes;
|
||||
|
||||
namespace Falcon.StoredProcedureRunnerTests
|
||||
{
|
||||
[Falcon.StoredProcedureRunner.FalconSPProcuderName("TestSp1")]
|
||||
[FalconSPProcuderName("TestSp1")]
|
||||
public class SqlserverModel
|
||||
{
|
||||
public int p1 { get; set; }
|
||||
|
|
Loading…
Reference in New Issue
Block a user