发布2.1版本,支持Oracle和SqlServer

This commit is contained in:
falcon 2022-01-10 14:43:21 +08:00
parent 2bcbeb4dae
commit 177d648979
32 changed files with 892 additions and 460 deletions

View File

@ -2,3 +2,10 @@
# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 # CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
dotnet_diagnostic.CS8618.severity = none 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

View File

@ -1,6 +1,6 @@
using System; using System;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner.Attributes
{ {
/// <summary> /// <summary>
/// 表示调用时候忽略此属性 /// 表示调用时候忽略此属性

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Data; using System.Data;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner.Attributes
{ {
/// <summary> /// <summary>
/// 定义存储过程参数方向。默认Input /// 定义存储过程参数方向。默认Input

View File

@ -1,6 +1,6 @@
using System; using System;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner.Attributes
{ {
/// <summary> /// <summary>
/// 定义名称 /// 定义名称

View File

@ -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;
}
}
}

View File

@ -1,6 +1,6 @@
using System; using System;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner.Attributes
{ {
/// <summary> /// <summary>
/// 定义存储过程名称 /// 定义存储过程名称

View File

@ -1,12 +1,12 @@
using System; using System;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner.Attributes
{ {
/// <summary> /// <summary>
/// 定义存储过程返回值类型 /// 定义存储过程返回值类型
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Class,AllowMultiple = false,Inherited = false)] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class FalconSPReturnTypeAttribute:Attribute public class FalconSPReturnTypeAttribute : Attribute
{ {
/// <summary> /// <summary>
/// 返回的数据类型 /// 返回的数据类型

View File

@ -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;
}
}

View File

@ -3,7 +3,7 @@
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner
{ {
/// <summary> /// <summary>
/// 设置返回对象值时候发生异常 /// 不支持的数据库类型
/// </summary> /// </summary>
public class DatabaseNotSupportedException : Exception public class DatabaseNotSupportedException : Exception
{ {

View File

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net5.0</TargetFrameworks> <TargetFrameworks>net5.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.0.0</Version> <Version>2.1.0</Version>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile> <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
<PackageProjectUrl>https://github.com/FalconWu2017/Falcon.StoredProcedureRunner</PackageProjectUrl> <PackageProjectUrl>https://github.com/FalconWu2017/Falcon.StoredProcedureRunner</PackageProjectUrl>
<RepositoryUrl>https://github.com/FalconWu2017/Falcon.StoredProcedureRunner</RepositoryUrl> <RepositoryUrl>https://github.com/FalconWu2017/Falcon.StoredProcedureRunner</RepositoryUrl>

View File

@ -6,6 +6,7 @@
/// </summary> /// </summary>
public enum FalconSPDbType public enum FalconSPDbType
{ {
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
// //
// 摘要: // 摘要:
// System.Int64. A 64-bit signed integer. // System.Int64. A 64-bit signed integer.
@ -201,7 +202,6 @@
OracleBoolean = 134, OracleBoolean = 134,
OracleJson = 135 OracleJson = 135
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
} }
} }

View File

@ -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; }
}
}

View File

@ -0,0 +1,7 @@
namespace Falcon.StoredProcedureRunner
{
/// <summary>
/// 面向Oracle的执行器
/// </summary>
public interface IOracleRunner : IRunner { }
}

View File

@ -15,7 +15,7 @@ namespace Falcon.StoredProcedureRunner
/// <typeparam name="TPrarmType">参数类型</typeparam> /// <typeparam name="TPrarmType">参数类型</typeparam>
/// <param name="db">数据上下文</param> /// <param name="db">数据上下文</param>
/// <param name="data">参数数据</param> /// <param name="data">参数数据</param>
int Execute<TPrarmType>(DbContext db,TPrarmType data); int Execute<TPrarmType>(DbContext db, TPrarmType data);
/// <summary> /// <summary>
/// 通过数据库上下文执行存储过程,并返回查询结果 /// 通过数据库上下文执行存储过程,并返回查询结果
@ -25,7 +25,7 @@ namespace Falcon.StoredProcedureRunner
/// <param name="returnType">返回结果项类型</param> /// <param name="returnType">返回结果项类型</param>
/// <param name="data">执行参数</param> /// <param name="data">执行参数</param>
/// <returns>查询结果枚举</returns> /// <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> /// <summary>
/// 存在sql注入风险执行Sql语句并将数据库返回结果以json数据对象返回。 /// 存在sql注入风险执行Sql语句并将数据库返回结果以json数据对象返回。
@ -33,6 +33,6 @@ namespace Falcon.StoredProcedureRunner
/// <param name="db">数据上下文</param> /// <param name="db">数据上下文</param>
/// <param name="sql">要执行的sql语句</param> /// <param name="sql">要执行的sql语句</param>
/// <returns>数据库返回值json格式</returns> /// <returns>数据库返回值json格式</returns>
string RunRaw(DbContext db,string sql); string RunRaw(DbContext db, string sql);
} }
} }

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using Falcon.StoredProcedureRunner.Attributes;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner
{ {
@ -12,7 +13,8 @@ namespace Falcon.StoredProcedureRunner
/// </summary> /// </summary>
/// <param name="services">注册服务集合</param> /// <param name="services">注册服务集合</param>
/// <returns>服务集合</returns> /// <returns>服务集合</returns>
public static IServiceCollection UseFalconSPRunner(this IServiceCollection services) { public static IServiceCollection UseFalconSPRunner(this IServiceCollection services)
{
return services.AddFalconSPRunner(); return services.AddFalconSPRunner();
} }
@ -21,8 +23,12 @@ namespace Falcon.StoredProcedureRunner
/// </summary> /// </summary>
/// <param name="services">注册服务集合</param> /// <param name="services">注册服务集合</param>
/// <returns>服务集合</returns> /// <returns>服务集合</returns>
public static IServiceCollection AddFalconSPRunner(this IServiceCollection services) { public static IServiceCollection AddFalconSPRunner(this IServiceCollection services)
return services.AddSingleton<IRunner,Runner>(); {
services.AddSingleton<IRunner, Runner>();
services.AddSingleton<IOracleRunner, OracleRunner>();
services.AddSingleton<ISqlServerRunner, SqlServerRunner>();
return services;
} }
} }

View File

@ -0,0 +1,7 @@
namespace Falcon.StoredProcedureRunner
{
/// <summary>
/// 面向SqlServer的执行器
/// </summary>
public interface ISqlServerRunner : IRunner { }
}

View 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);
}
}
}

View 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;
}
}

View File

@ -0,0 +1,17 @@
namespace Falcon.StoredProcedureRunner
{
/// <summary>
/// 获取返回值方式
/// </summary>
public enum ReturnModel
{
/// <summary>
/// 通过存储过程返回值获取数据
/// </summary>
Return = 1,
/// <summary>
/// 通过临时表表获取数据
/// </summary>
TempTable = 2
}
}

View File

@ -1,360 +1,54 @@
using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Linq;
using Oracle.ManagedDataAccess.Client;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Falcon.StoredProcedureRunner namespace Falcon.StoredProcedureRunner
{ {
/// <summary> /// <summary>
/// 存储过程执行 /// 通用存储过程执行器
/// </summary> /// </summary>
public partial class Runner : IRunner public class Runner : IRunner
{ {
/// <summary> /// <summary>
/// 执行无返回值的存储过程 /// 注册的所有服务
/// </summary> /// </summary>
/// <typeparam name="TPrarmType">参数类型</typeparam> public IServiceProvider Service { get; }
/// <param name="db">数据上下文</param> /// <summary>
/// <param name="data">参数数据</param> /// 通过注册的服务实例化执行器
/// </summary>
/// <param name="service">服务集合</param>
public Runner(IServiceProvider service)
{
Service = service;
}
public int Execute<TPrarmType>(DbContext db, TPrarmType data) public int Execute<TPrarmType>(DbContext db, TPrarmType data)
{ {
throw new NotSupportedException(); return GetRunner(db).Execute<TPrarmType>(db, data);
//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 IEnumerable<object> Run(DbContext db, Type prarmType, Type returnType, object data) 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) public string RunRaw(DbContext db, string sql)
{ {
var connection = db.Database.GetDbConnection(); return GetRunner(db).RunRaw(db, sql);
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>
/// 内部保护方法 /// 获取特定类型的数据库runnner
/// </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>
/// 创建存储过程参数
/// </summary> /// </summary>
/// <param name="db">数据库上下文</param> /// <param name="db">数据库上下文</param>
/// <param name="name">参数名称</param> /// <returns>特定类型的执行器</returns>
/// <param name="val">参数值</param> /// <exception cref="DatabaseNotSupportedException"></exception>
/// <returns>参数</returns> protected IRunner GetRunner(DbContext db)
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
{ {
return return
dbf.IsSqlServer() ? new SqlParameter(name, val) : db.Database.IsOracle() ? Service.GetService<IOracleRunner>() :
dbf.IsOracle() ? new OracleParameter(name, val) : db.Database.IsSqlServer() ? Service.GetService<IOracleRunner>() :
throw new DatabaseNotSupportedException(); 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(',');
//}
}
} }

View 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);
}
}

View 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;
}
}
}

View File

@ -0,0 +1,10 @@
namespace Falcon.StoredProcedureRunner
{
/// <summary>
/// Sqlserver执行配置
/// </summary>
public class SqlServerRunnerOtions
{
}
}

View File

@ -3,5 +3,11 @@
"ver": "", "ver": "",
"oracle": "", "oracle": "",
"sqlserver": "" "sqlserver": ""
},
"OracleRunner": {
"ReturnModel": 2
},
"SqlRunner": {
} }
} }

View File

@ -13,6 +13,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" 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.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="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> <PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
@ -35,4 +36,8 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Falcon\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,5 @@
using Falcon.StoredProcedureRunner; using Falcon.StoredProcedureRunner;
using Falcon.StoredProcedureRunner.Attributes;
using System.Data; using System.Data;
namespace Falcon.StoredProcedureRunnerTests namespace Falcon.StoredProcedureRunnerTests
@ -24,27 +25,24 @@ namespace Falcon.StoredProcedureRunnerTests
/// </summary> /// </summary>
public class Tjjk_Tjgh public class Tjjk_Tjgh
{ {
/// <summary>
/// 身份证号码
/// </summary>
public string v_sfz { get; set; }
/// <summary> /// <summary>
/// 医疗机构代码 /// 医疗机构代码
/// </summary> /// </summary>
public string v_yljgdm { get; set; } public string v_yljgdm { get; set; }
/// <summary> /// <summary>
/// 身份证号码
/// </summary>
public string v_sfz { get; set; }
/// <summary>
/// 挂号日期 格式yyyyMMdd /// 挂号日期 格式yyyyMMdd
/// </summary> /// </summary>
public string v_ghrq { get; set; } public string v_ghrq { get; set; }
[FalconSPPrarmDirection(ParameterDirection.Output)]
[FalconSPPrarmType(FalconSPDbType.OracleRefCursor)]
public object v_data { get; set; }
} }
/// <summary> /// <summary>
/// 挂号查询结果 /// 挂号查询结果
/// </summary> /// </summary>
[FalconSPTempTable("TT_Tjjk_Tjgh")]
public class Tjjk_TjghResult public class Tjjk_TjghResult
{ {
/// <summary> /// <summary>

View File

@ -3,33 +3,53 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq; using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Oracle.ManagedDataAccess.Client;
using System.Data;
using System.ComponentModel.DataAnnotations;
namespace Falcon.StoredProcedureRunner.Tests namespace Falcon.StoredProcedureRunner.Tests
{ {
[TestClass()] [TestClass()]
public class RunnerTests public class RunnerTests
{ {
[TestMethod("通用测试")] [TestMethod("Runner创建测试")]
public void RunTest() public void RunTest()
{ {
OracleTest(); var config = GetConfiguration();
System.Console.WriteLine("---------------------"); var services = CreateServiceScope(config);
SqlserverTest(); 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() public void SqlserverTest()
{ {
System.Console.WriteLine("SqlserverTest start!"); var config = GetConfiguration();
var configurationBuilder = new ConfigurationBuilder(); var services = CreateServiceScope(config);
configurationBuilder.AddJsonFile("AppSettings.json"); var db = CreateSqlDbContext(config);
configurationBuilder.AddUserSecrets(this.GetType().Assembly); Assert.IsNotNull(db);
var config = configurationBuilder.Build(); var runner = GetSqlRunner(services);
var sql = config.GetSection("db:sqlserver").Value; Assert.IsNotNull(runner);
var buider = new DbContextOptionsBuilder();
var db = new DbContext(buider.UseSqlServer(sql).Options);
IRunner runner = new Runner();
var result = runner.Run<SqlserverModel, SqlserverModelResult>(db, new SqlserverModel var result = runner.Run<SqlserverModel, SqlserverModelResult>(db, new SqlserverModel
{ {
p1 = 1, p1 = 1,
@ -44,54 +64,21 @@ namespace Falcon.StoredProcedureRunner.Tests
System.Console.WriteLine("SqlserverTest over!"); System.Console.WriteLine("SqlserverTest over!");
} }
[TestMethod()] [TestMethod("Oracle执行测试")]
public void OracleTest() public void OracleTest()
{ {
System.Console.WriteLine("OracleTest start!"); var config = GetConfiguration();
var configurationBuilder = new ConfigurationBuilder(); var services = CreateServiceScope(config);
configurationBuilder.AddJsonFile("AppSettings.json"); var db = CreateOracleDbContext(config);
configurationBuilder.AddUserSecrets(this.GetType().Assembly); Assert.IsNotNull(db);
var config = configurationBuilder.Build(); var runner = GetOracleRunner(services);
var ora = config.GetSection("db:oracle").Value; Assert.IsNotNull(runner);
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<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 var result = runner.Run<Tjjk_Tjgh, Tjjk_TjghResult>(db, new Tjjk_Tjgh
{ {
v_yljgdm = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
v_ghrq = "20211105", v_ghrq = "20211105",
v_sfz = "610528199002165174", v_sfz = "610528199002165174",
v_yljgdm = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113",
}).ToList(); }).ToList();
Assert.IsNotNull(result); Assert.IsNotNull(result);
System.Console.WriteLine("result ok"); System.Console.WriteLine("result ok");
@ -101,31 +88,142 @@ namespace Falcon.StoredProcedureRunner.Tests
System.Console.WriteLine("OracleTest over!"); System.Console.WriteLine("OracleTest over!");
} }
[TestMethod()] [TestMethod("Oracle原始执行执行测试")]
public void GetDoctorDataTest() 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 ora = config.GetSection("db:oracle").Value;
var oraVer = config.GetSection("db:ver").Value; var oraVer = config.GetSection("db:ver").Value;
var buider = new DbContextOptionsBuilder(); var buider = new DbContextOptionsBuilder();
var db = new DbContext(buider.UseOracle(ora, o => o.UseOracleSQLCompatibility(oraVer)).Options); return 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!");
} }
///// <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;
}
} }
} }

View File

@ -1,12 +1,8 @@
using System; using Falcon.StoredProcedureRunner.Attributes;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Falcon.StoredProcedureRunnerTests namespace Falcon.StoredProcedureRunnerTests
{ {
[Falcon.StoredProcedureRunner.FalconSPProcuderName("TestSp1")] [FalconSPProcuderName("TestSp1")]
public class SqlserverModel public class SqlserverModel
{ {
public int p1 { get; set; } public int p1 { get; set; }