diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 0000000..22524f2 --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 +dotnet_diagnostic.CS8618.severity = none diff --git a/src/Faclon.StoredProcedureRunner.Example/Database/MyDb.cs b/src/Faclon.StoredProcedureRunner.Example/Database/MyDb.cs deleted file mode 100644 index 3188ae5..0000000 --- a/src/Faclon.StoredProcedureRunner.Example/Database/MyDb.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Faclon.StoredProcedureRunner.Example.Database.sp; -using Microsoft.EntityFrameworkCore; -using Falcon.StoredProcedureRunner; - -namespace Faclon.StoredProcedureRunner.Example.Database -{ - public class MyDb:DbContext - { - public IRunner SpRunner { get; set; } - - public MyDb(DbContextOptions options,IRunner spRunner) : base(options) { - this.SpRunner = spRunner; - } - - public IEnumerable RunSp1(Sp1 data) { - return this.SpRunner.Run(this,data); - } - - public int RunSp1No(Sp1 data) { - return this.SpRunner.Execute(this,data); - } - } -} diff --git a/src/Faclon.StoredProcedureRunner.Example/Database/sp/Sp1.cs b/src/Faclon.StoredProcedureRunner.Example/Database/sp/Sp1.cs deleted file mode 100644 index 4910096..0000000 --- a/src/Faclon.StoredProcedureRunner.Example/Database/sp/Sp1.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Falcon.StoredProcedureRunner; - -namespace Faclon.StoredProcedureRunner.Example.Database.sp -{ - /// - /// 测试用存储过程 - /// - [FalconSPReturnType(typeof(Sp1_Result))] - [FalconSPProcuderName("TestSp1")] - public class Sp1 - { - /// - /// 整数1 - /// - public int P1 { get; set; } = 1; - /// - /// 整数2 - /// - public int P2 { get; set; } = 2; - /// - /// 字符串P3 - /// - [FalconSPPrarmType(System.Data.SqlDbType.VarChar)] - public string P3 { get; set; } = "abcd"; - } - /// - /// 存储过程执行结果 - /// - public class Sp1_Result - { - /// - /// 结果行号 - /// - public int Id { get; set; } - /// - /// 求和 - /// - public int Jia { get; set; } - /// - /// 求差 - /// - public int Jian { get; set; } - /// - /// 求乘积 - /// - public int Chen { get; set; } - /// - /// 求除法 - /// - public double Chu { get; set; } - /// - /// 字符串返回值 - /// - public string s { get; set; } - } -} diff --git a/src/Faclon.StoredProcedureRunner.Example/Faclon.StoredProcedureRunner.Example.csproj b/src/Faclon.StoredProcedureRunner.Example/Faclon.StoredProcedureRunner.Example.csproj deleted file mode 100644 index fb47f2b..0000000 --- a/src/Faclon.StoredProcedureRunner.Example/Faclon.StoredProcedureRunner.Example.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - Exe - net5;netcoreapp3.1 - - - - - - - - - - - - - diff --git a/src/Faclon.StoredProcedureRunner.Example/Program.cs b/src/Faclon.StoredProcedureRunner.Example/Program.cs deleted file mode 100644 index 020ac1f..0000000 --- a/src/Faclon.StoredProcedureRunner.Example/Program.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using Faclon.StoredProcedureRunner.Example.Database; -using Falcon.StoredProcedureRunner; -using Microsoft.EntityFrameworkCore; - -namespace Faclon.StoredProcedureRunner.Example -{ - class Program - { - static void Main(string[] args) { - IRunner runner = new Runner(); - var conStr = "Server =.\\SQLSERVER2008R2;Database = test;User ID = sa;Password = 111"; - var opb = new DbContextOptionsBuilder(); - opb.UseSqlServer(conStr); - var db = new MyDb(opb.Options,runner); - Console.WriteLine("测试调用存储过程,获取返回值"); - var r = db.RunSp1(new Database.sp.Sp1()); - Console.WriteLine("返回记录数{0},应该为2",r.Count()); - var fir = r.First(); - Console.WriteLine("Id为{0},应该为1",fir.Id); - Console.WriteLine("Jia{0},应该为3",fir.Jia); - Console.WriteLine("Jian{0},应该为-1",fir.Jian); - Console.WriteLine("Chen{0},应该为2",fir.Chen); - Console.WriteLine("Chu{0},应该为0.5",fir.Chu); - Console.WriteLine("s{0},应该为abc1",fir.s); - - Console.WriteLine("测试无返回值调用"); - var r1 = db.RunSp1No(new Database.sp.Sp1()); - Console.WriteLine("返回结果{0}",r1); - } - } -} diff --git a/src/Falcon.StoredProcedureRunner.sln b/src/Falcon.StoredProcedureRunner.sln index cc11cfa..a410924 100644 --- a/src/Falcon.StoredProcedureRunner.sln +++ b/src/Falcon.StoredProcedureRunner.sln @@ -1,11 +1,16 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30804.86 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.StoredProcedureRunner", "Falcon.StoredProcedureRunner\Falcon.StoredProcedureRunner.csproj", "{13D3139B-60C2-4785-ADCB-4F839BDEC3C4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.StoredProcedureRunner", "Falcon.StoredProcedureRunner\Falcon.StoredProcedureRunner.csproj", "{57A72FF8-1FA8-47A1-8F96-30740890C877}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faclon.StoredProcedureRunner.Example", "Faclon.StoredProcedureRunner.Example\Faclon.StoredProcedureRunner.Example.csproj", "{40610016-0C9C-462D-B352-49D6C33DA5FC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.StoredProcedureRunnerTests", "Falcon.StoredProcedureRunnerTests\Falcon.StoredProcedureRunnerTests.csproj", "{E872783D-5387-49BE-9845-7F755F29696E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C43175B4-F376-4DC3-B46E-CCD1E6ADE67D}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,19 +18,19 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {13D3139B-60C2-4785-ADCB-4F839BDEC3C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {13D3139B-60C2-4785-ADCB-4F839BDEC3C4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {13D3139B-60C2-4785-ADCB-4F839BDEC3C4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {13D3139B-60C2-4785-ADCB-4F839BDEC3C4}.Release|Any CPU.Build.0 = Release|Any CPU - {40610016-0C9C-462D-B352-49D6C33DA5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {40610016-0C9C-462D-B352-49D6C33DA5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {40610016-0C9C-462D-B352-49D6C33DA5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {40610016-0C9C-462D-B352-49D6C33DA5FC}.Release|Any CPU.Build.0 = Release|Any CPU + {57A72FF8-1FA8-47A1-8F96-30740890C877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {57A72FF8-1FA8-47A1-8F96-30740890C877}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57A72FF8-1FA8-47A1-8F96-30740890C877}.Release|Any CPU.ActiveCfg = Release|Any CPU + {57A72FF8-1FA8-47A1-8F96-30740890C877}.Release|Any CPU.Build.0 = Release|Any CPU + {E872783D-5387-49BE-9845-7F755F29696E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E872783D-5387-49BE-9845-7F755F29696E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E872783D-5387-49BE-9845-7F755F29696E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E872783D-5387-49BE-9845-7F755F29696E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7ECD6C47-0547-4FB7-A481-829D28302EFD} + SolutionGuid = {19EB0FAF-B61A-422D-90AC-A602956F6875} EndGlobalSection EndGlobal diff --git a/src/Falcon.StoredProcedureRunner/DatabaseNotSupportedException.cs b/src/Falcon.StoredProcedureRunner/DatabaseNotSupportedException.cs new file mode 100644 index 0000000..47a71ae --- /dev/null +++ b/src/Falcon.StoredProcedureRunner/DatabaseNotSupportedException.cs @@ -0,0 +1,17 @@ +using System; + +namespace Falcon.StoredProcedureRunner +{ + /// + /// 设置返回对象值时候发生异常 + /// + public class DatabaseNotSupportedException : Exception + { + /// + /// 实例化不支持的数据库对象异常 + /// + public DatabaseNotSupportedException() : base("仅仅支持Oracle和SqlServer数据库") + { + } + } +} diff --git a/src/Falcon.StoredProcedureRunner/Falcon.StoredProcedureRunner.csproj b/src/Falcon.StoredProcedureRunner/Falcon.StoredProcedureRunner.csproj index 0bb76f9..c506633 100644 --- a/src/Falcon.StoredProcedureRunner/Falcon.StoredProcedureRunner.csproj +++ b/src/Falcon.StoredProcedureRunner/Falcon.StoredProcedureRunner.csproj @@ -1,33 +1,23 @@ + - net5;netstandard2.1;netstandard2.0; - true - 1.4.0 - bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml - https://github.com/FalconWu2017/Falcon.StoredProcedureRunner - https://github.com/FalconWu2017/Falcon.StoredProcedureRunner - EF Core 存储过程执行组件,可以按照ORM方式执行存储过程 - Falcon + net5.0 + true + 2.0.0 + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + https://github.com/FalconWu2017/Falcon.StoredProcedureRunner + https://github.com/FalconWu2017/Falcon.StoredProcedureRunner + EF Core 存储过程执行组件,可以按照ORM方式执行存储过程 + Falcon - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + diff --git a/src/Falcon.StoredProcedureRunner/FalconSPDbType.cs b/src/Falcon.StoredProcedureRunner/FalconSPDbType.cs new file mode 100644 index 0000000..fc69fa0 --- /dev/null +++ b/src/Falcon.StoredProcedureRunner/FalconSPDbType.cs @@ -0,0 +1,207 @@ +namespace Falcon.StoredProcedureRunner +{ + + /// + /// 定义数据库数据类型 + /// + public enum FalconSPDbType + { + // + // 摘要: + // System.Int64. A 64-bit signed integer. + SqlServerBigInt = 0, + // + // 摘要: + // System.Array of type System.Byte. A fixed-length stream of binary data ranging + // between 1 and 8,000 bytes. + SqlServerBinary = 1, + // + // 摘要: + // System.Boolean. An unsigned numeric value that can be 0, 1, or null. + SqlServerBit = 2, + // + // 摘要: + // System.String. A fixed-length stream of non-Unicode characters ranging between + // 1 and 8,000 characters. + SqlServerChar = 3, + // + // 摘要: + // System.DateTime. Date and time data ranging in value from January 1, 1753 to + // December 31, 9999 to an accuracy of 3.33 milliseconds. + SqlServerDateTime = 4, + // + // 摘要: + // System.Decimal. A fixed precision and scale numeric value between -10 38 -1 and + // 10 38 -1. + SqlServerDecimal = 5, + // + // 摘要: + // System.Double. A floating point number within the range of -1.79E +308 through + // 1.79E +308. + SqlServerFloat = 6, + // + // 摘要: + // System.Array of type System.Byte. A variable-length stream of binary data ranging + // from 0 to 2 31 -1 (or 2,147,483,647) bytes. + SqlServerImage = 7, + // + // 摘要: + // System.Int32. A 32-bit signed integer. + SqlServerInt = 8, + // + // 摘要: + // System.Decimal. A currency value ranging from -2 63 (or -9,223,372,036,854,775,808) + // to 2 63 -1 (or +9,223,372,036,854,775,807) with an accuracy to a ten-thousandth + // of a currency unit. + SqlServerMoney = 9, + // + // 摘要: + // System.String. A fixed-length stream of Unicode characters ranging between 1 + // and 4,000 characters. + SqlServerNChar = 10, + // + // 摘要: + // System.String. A variable-length stream of Unicode data with a maximum length + // of 2 30 - 1 (or 1,073,741,823) characters. + SqlServerNText = 11, + // + // 摘要: + // System.String. A variable-length stream of Unicode characters ranging between + // 1 and 4,000 characters. Implicit conversion fails if the string is greater than + // 4,000 characters. Explicitly set the object when working with strings longer + // than 4,000 characters. Use System.Data.SqlDbType.NVarChar when the database column + // is nvarchar(max). + SqlServerNVarChar = 12, + // + // 摘要: + // System.Single. A floating point number within the range of -3.40E +38 through + // 3.40E +38. + SqlServerReal = 13, + // + // 摘要: + // System.Guid. A globally unique identifier (or GUID). + SqlServerUniqueIdentifier = 14, + // + // 摘要: + // System.DateTime. Date and time data ranging in value from January 1, 1900 to + // June 6, 2079 to an accuracy of one minute. + SqlServerSmallDateTime = 0xF, + // + // 摘要: + // System.Int16. A 16-bit signed integer. + SqlServerSmallInt = 0x10, + // + // 摘要: + // System.Decimal. A currency value ranging from -214,748.3648 to +214,748.3647 + // with an accuracy to a ten-thousandth of a currency unit. + SqlServerSmallMoney = 17, + // + // 摘要: + // System.String. A variable-length stream of non-Unicode data with a maximum length + // of 2 31 -1 (or 2,147,483,647) characters. + SqlServerText = 18, + // + // 摘要: + // System.Array of type System.Byte. Automatically generated binary numbers, which + // are guaranteed to be unique within a database. timestamp is used typically as + // a mechanism for version-stamping table rows. The storage size is 8 bytes. + SqlServerTimestamp = 19, + // + // 摘要: + // System.Byte. An 8-bit unsigned integer. + SqlServerTinyInt = 20, + // + // 摘要: + // System.Array of type System.Byte. A variable-length stream of binary data ranging + // between 1 and 8,000 bytes. Implicit conversion fails if the byte array is greater + // than 8,000 bytes. Explicitly set the object when working with byte arrays larger + // than 8,000 bytes. + SqlServerVarBinary = 21, + // + // 摘要: + // System.String. A variable-length stream of non-Unicode characters ranging between + // 1 and 8,000 characters. Use System.Data.SqlDbType.VarChar when the database column + // is varchar(max). + SqlServerVarChar = 22, + // + // 摘要: + // System.Object. A special data type that can contain numeric, string, binary, + // or date data as well as the SQL Server values Empty and Null, which is assumed + // if no other type is declared. + SqlServerVariant = 23, + // + // 摘要: + // An XML value. Obtain the XML as a string using the System.Data.SqlClient.SqlDataReader.GetValue(System.Int32) + // method or System.Data.SqlTypes.SqlXml.Value property, or as an System.Xml.XmlReader + // by calling the System.Data.SqlTypes.SqlXml.CreateReader method. + SqlServerXml = 25, + // + // 摘要: + // A SQL Server user-defined type (UDT). + SqlServerUdt = 29, + // + // 摘要: + // A special data type for specifying structured data contained in table-valued + // parameters. + SqlServerStructured = 30, + // + // 摘要: + // Date data ranging in value from January 1,1 AD through December 31, 9999 AD. + SqlServerDate = 0x1F, + // + // 摘要: + // Time data based on a 24-hour clock. Time value range is 00:00:00 through 23:59:59.9999999 + // with an accuracy of 100 nanoseconds. Corresponds to a SQL Server time value. + SqlServerTime = 0x20, + // + // 摘要: + // Date and time data. Date value range is from January 1,1 AD through December + // 31, 9999 AD. Time value range is 00:00:00 through 23:59:59.9999999 with an accuracy + // of 100 nanoseconds. + SqlServerDateTime2 = 33, + // + // 摘要: + // Date and time data with time zone awareness. Date value range is from January + // 1,1 AD through December 31, 9999 AD. Time value range is 00:00:00 through 23:59:59.9999999 + // with an accuracy of 100 nanoseconds. Time zone value range is -14:00 through + // +14:00. + SqlServerDateTimeOffset = 34, + + OracleBFile = 101, + OracleBlob = 102, + OracleByte = 103, + OracleChar = 104, + OracleClob = 105, + OracleDate = 106, + OracleDecimal = 107, + OracleDouble = 108, + OracleLong = 109, + OracleLongRaw = 110, + OracleInt16 = 111, + OracleInt32 = 112, + OracleInt64 = 113, + OracleIntervalDS = 114, + OracleIntervalYM = 115, + OracleNClob = 116, + OracleNChar = 117, + OracleNVarchar2 = 119, + OracleRaw = 120, + OracleRefCursor = 121, + OracleSingle = 122, + OracleTimeStamp = 123, + OracleTimeStampLTZ = 124, + OracleTimeStampTZ = 125, + OracleVarchar2 = 126, + OracleXmlType = 0x7F, + OracleArray = 0x80, + OracleObject = 129, + OracleRef = 130, + OracleBinaryDouble = 132, + OracleBinaryFloat = 133, + OracleBoolean = 134, + OracleJson = 135 + + } + + +} diff --git a/src/Falcon.StoredProcedureRunner/FalconSPIgnoreAttribute.cs b/src/Falcon.StoredProcedureRunner/FalconSPIgnoreAttribute.cs index 5a5c0e3..dda3222 100644 --- a/src/Falcon.StoredProcedureRunner/FalconSPIgnoreAttribute.cs +++ b/src/Falcon.StoredProcedureRunner/FalconSPIgnoreAttribute.cs @@ -5,8 +5,8 @@ namespace Falcon.StoredProcedureRunner /// /// 表示调用时候忽略此属性 /// - [AttributeUsage(AttributeTargets.Property)] - public class FalconSPIgnoreAttribute:Attribute + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public class FalconSPIgnoreAttribute : Attribute { } } diff --git a/src/Falcon.StoredProcedureRunner/FalconSPPrarmDirectionAttribute.cs b/src/Falcon.StoredProcedureRunner/FalconSPPrarmDirectionAttribute.cs new file mode 100644 index 0000000..3203f0d --- /dev/null +++ b/src/Falcon.StoredProcedureRunner/FalconSPPrarmDirectionAttribute.cs @@ -0,0 +1,25 @@ +using System; +using System.Data; + +namespace Falcon.StoredProcedureRunner +{ + /// + /// 定义存储过程参数方向。默认Input + /// + [AttributeUsage(AttributeTargets.Property,AllowMultiple =false,Inherited =false)] + public class FalconSPPrarmDirectionAttribute:Attribute + { + /// + /// 参数方向 + /// + public ParameterDirection Direction { get; } + + /// + /// 定义参数方向 + /// + /// + public FalconSPPrarmDirectionAttribute(ParameterDirection direction) + => this.Direction = direction; + + } +} diff --git a/src/Falcon.StoredProcedureRunner/FalconSPPrarmNameAttribute.cs b/src/Falcon.StoredProcedureRunner/FalconSPPrarmNameAttribute.cs index ee081e7..2dd39f6 100644 --- a/src/Falcon.StoredProcedureRunner/FalconSPPrarmNameAttribute.cs +++ b/src/Falcon.StoredProcedureRunner/FalconSPPrarmNameAttribute.cs @@ -5,6 +5,7 @@ namespace Falcon.StoredProcedureRunner /// /// 定义名称 /// + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class FalconSPPrarmNameAttribute:Attribute { /// diff --git a/src/Falcon.StoredProcedureRunner/FalconSPPrarmTypeAttribute.cs b/src/Falcon.StoredProcedureRunner/FalconSPPrarmTypeAttribute.cs index ba8e80e..5c206e4 100644 --- a/src/Falcon.StoredProcedureRunner/FalconSPPrarmTypeAttribute.cs +++ b/src/Falcon.StoredProcedureRunner/FalconSPPrarmTypeAttribute.cs @@ -1,21 +1,21 @@ using System; -using System.Data; namespace Falcon.StoredProcedureRunner { /// /// 定义存储过程参数类型 /// + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class FalconSPPrarmTypeAttribute:Attribute { /// /// 参数名 /// - public SqlDbType PType { get; set; } + public FalconSPDbType PType { get; set; } /// /// 定于存储过程参数名称 /// - /// 参数类型 - public FalconSPPrarmTypeAttribute(SqlDbType pType) { this.PType = pType; } + /// 参数类型.DbType + public FalconSPPrarmTypeAttribute(FalconSPDbType pDbType) { this.PType = pDbType; } } } diff --git a/src/Falcon.StoredProcedureRunner/IRunnerExtend.cs b/src/Falcon.StoredProcedureRunner/IRunnerExtend.cs index fbf76af..c7e407f 100644 --- a/src/Falcon.StoredProcedureRunner/IRunnerExtend.cs +++ b/src/Falcon.StoredProcedureRunner/IRunnerExtend.cs @@ -45,8 +45,8 @@ namespace Falcon.StoredProcedureRunner return runner.Run(db,typeof(TPrarmType),typeof(TReturnType),data).Cast(); } catch(InvalidCastException ice) { throw new ReturnTypeCastException(ice); - } catch(Exception ex) { - throw ex; + } catch(Exception) { + throw; } } diff --git a/src/Falcon.StoredProcedureRunner/ReturnDataSetValueException.cs b/src/Falcon.StoredProcedureRunner/ReturnDataSetValueException.cs index 10b4b7c..c691d1d 100644 --- a/src/Falcon.StoredProcedureRunner/ReturnDataSetValueException.cs +++ b/src/Falcon.StoredProcedureRunner/ReturnDataSetValueException.cs @@ -6,7 +6,7 @@ namespace Falcon.StoredProcedureRunner /// /// 设置返回对象值时候发生异常 /// - public class ReturnDataSetValueException:Exception + public class ReturnDataSetValueException : Exception { /// /// 实例化一个给返回数据设置值的异常 @@ -16,7 +16,7 @@ namespace Falcon.StoredProcedureRunner /// 要设置值的属性 /// 要设置的值 /// 内部异常 - public ReturnDataSetValueException(int rowId,string cName, PropertyInfo pi,object value,Exception innException) - : base($"存储过程返回第[{rowId}]行[{cName}]列数据值为({value.GetType().FullName})[{value}]无法赋给属性({pi.PropertyType.FullName})[{pi.Name}]。",innException) { } + public ReturnDataSetValueException(int rowId, string cName, PropertyInfo pi, object value, Exception innException) + : base($"存储过程返回第[{rowId}]行[{cName}]列数据值为({value.GetType().FullName})[{value}]无法赋给属性({pi.PropertyType.FullName})[{pi.Name}]。", innException) { } } } diff --git a/src/Falcon.StoredProcedureRunner/Runner.cs b/src/Falcon.StoredProcedureRunner/Runner.cs index e1fb9ed..580ab97 100644 --- a/src/Falcon.StoredProcedureRunner/Runner.cs +++ b/src/Falcon.StoredProcedureRunner/Runner.cs @@ -1,19 +1,20 @@ -using System; +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; -using Microsoft.Data.SqlClient; -using Microsoft.EntityFrameworkCore; namespace Falcon.StoredProcedureRunner { /// /// 存储过程执行 /// - public partial class Runner:IRunner + public partial class Runner : IRunner { /// /// 执行无返回值的存储过程 @@ -21,12 +22,17 @@ namespace Falcon.StoredProcedureRunner /// 参数类型 /// 数据上下文 /// 参数数据 - public int Execute(DbContext db,TPrarmType data) { - var parms = getParams(typeof(TPrarmType),data).ToArray(); - var pName = getProcuderName(); - var paramStr = getParamStr(typeof(TPrarmType),data); - var str = $"exec {pName} {paramStr}"; - return db.Database.ExecuteSqlRaw(str,parms); + public int Execute(DbContext db, TPrarmType data) + { + throw new NotSupportedException(); + //var parms = getParams(db, typeof(TPrarmType), data).ToArray(); + //var pName = getProcuderName(); + //var conn = db.Database.GetDbConnection(); + + + //var paramStr = getParamStr(typeof(TPrarmType), data); + //var str = $"exec {pName} {paramStr}"; + //return db.Database.ExecuteSqlRaw(str, parms); } /// @@ -37,33 +43,40 @@ namespace Falcon.StoredProcedureRunner /// 返回值类型 /// 存储过程参数 /// 查询结果枚举 - public IEnumerable Run(DbContext db,Type prarmType,Type returnType,object data) { + public IEnumerable Run(DbContext db, Type prarmType, Type returnType, object data) + { var pm = getProcuderName(prarmType); - var paras = getParams(prarmType,data).ToArray(); + var paras = getParams(db, prarmType, data).ToArray(); var connection = db.Database.GetDbConnection(); - using(var cmd = connection.CreateCommand()) { + using (var cmd = connection.CreateCommand()) + { cmd.CommandText = pm; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddRange(paras); connection.Open(); var dr = cmd.ExecuteReader(); var result = new List(); - if(!dr.CanGetColumnSchema()) + if (!dr.CanGetColumnSchema()) return result; int rowId = 0; - while(dr.Read()) { + while (dr.Read()) + { var item = returnType.Assembly.CreateInstance(returnType.FullName); var columnSchema = dr.GetColumnSchema(); - for(var i = 0;i < columnSchema.Count;i++) { + 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) + 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); + try + { + pi.SetValue(item, value); + } + catch (Exception ex) + { + throw new ReturnDataSetValueException(rowId, name, pi, value, ex); } } result.Add(item); @@ -80,20 +93,24 @@ namespace Falcon.StoredProcedureRunner /// 数据上下文 /// 要执行的sql语句 /// 数据库返回值json格式 - public string RunRaw(DbContext db,string sql) { + public string RunRaw(DbContext db, string sql) + { var connection = db.Database.GetDbConnection(); - using(var cmd = connection.CreateCommand()) { + 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()) + if (!dr.CanGetColumnSchema()) return ""; - while(dr.Read()) { + while (dr.Read()) + { var item = new StringBuilder(); var columnSchema = dr.GetColumnSchema(); - for(var i = 0;i < columnSchema.Count;i++) { + 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}\","); @@ -115,12 +132,10 @@ namespace Falcon.StoredProcedureRunner /// 获取存储过程名 /// /// 参数类型 - private static string getProcuderName(Type pramType) { + private static string getProcuderName(Type pramType) + { var attr = pramType.GetCustomAttribute(); - if(attr != null && attr is FalconSPProcuderNameAttribute pna && !string.IsNullOrEmpty(pna.ProcuderName)) { - return pna.ProcuderName; - } - return pramType.Name; + return attr?.ProcuderName ?? pramType.Name; } /// @@ -128,20 +143,25 @@ namespace Falcon.StoredProcedureRunner /// ///数据的类型 /// 参数实例 - private static IEnumerable getParams(Type type,object data) { - if(data == null) + private static IEnumerable getParams(DbContext db, Type type, object data) + { + if (data == null) yield break; - foreach(var p in type.GetProperties()) { - if(!p.CanRead || ignoreProp(p)) + 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); - if(pt.HasValue) { - var np = new SqlParameter($"@{getPrarmName(p)}",pt.Value); - np.Value = p.GetValue(data); - yield return np; - } else { - yield return new SqlParameter($"@{getPrarmName(p)}",p.GetValue(data)); - } + var para = CreateDbParameter(db, name, val, pt); + para.Direction = GetParaDirection(p); + yield return para; } } @@ -149,19 +169,61 @@ namespace Falcon.StoredProcedureRunner /// 获取存储过程参数类型 /// /// 对应的属性 - private static SqlDbType? getPrarmType(PropertyInfo p) { - var np = p.GetCustomAttribute(true); - if(np != null && np is FalconSPPrarmTypeAttribute na) { - return na.PType; + private static int? getPrarmType(PropertyInfo p) + { + var np = p.GetCustomAttribute(); + if (np != null && np is FalconSPPrarmTypeAttribute na) + { + return (int)np.PType; } return null; } + /// + /// 创建存储过程参数 + /// + /// 数据库上下文 + /// 参数名称 + /// 参数值 + /// 参数 + 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 + dbf.IsSqlServer() ? new SqlParameter(name, val) : + dbf.IsOracle() ? new OracleParameter(name, val) : + throw new DatabaseNotSupportedException(); + } + } + + /// + /// 获取参数的方向。默认Input + /// + /// 参数映射属性 + /// 方向或null + private static ParameterDirection GetParaDirection(PropertyInfo p) + { + var attr = p.GetCustomAttribute(); + return attr == null ? ParameterDirection.Input : attr.Direction; + } + /// /// 是否忽略属性 /// /// 要检查的属性 - private static bool ignoreProp(PropertyInfo p) { + private static bool isIgnoreProp(PropertyInfo p) + { return p.GetCustomAttribute(true) != null; } @@ -169,34 +231,29 @@ namespace Falcon.StoredProcedureRunner /// 获取存储过程参数名称 /// /// 对应的属性 - private static string getPrarmName(PropertyInfo p) { + private static string getPrarmName(PropertyInfo p, string prefixChar) + { var np = p.GetCustomAttribute(true); - if(np != null && np is FalconSPPrarmNameAttribute na) { - return na.Name; + if (np != null && np is FalconSPPrarmNameAttribute na) + { + var name = na.Name; + return name.StartsWith(prefixChar) ? name : prefixChar + name; } - return p.Name; + return prefixChar + p.Name; } - /// - /// 获取存储过程名 - /// - /// 参数模型 - private static string getProcuderName() { - var attr = typeof(T).GetCustomAttribute(true); - if(attr != null && attr is FalconSPProcuderNameAttribute pna && !string.IsNullOrEmpty(pna.ProcuderName)) { - return pna.ProcuderName; - } - return typeof(T).Name; - } /// /// 忽略大小写获取类型的属性 /// /// 类型 /// 属性名称 /// 属性 - private static PropertyInfo getProperty(Type t,string name) { - foreach(var item in t.GetProperties()) { - if(item.Name.ToLower() == name.ToLower()) { + private static PropertyInfo getProperty(Type t, string name) + { + foreach (var item in t.GetProperties()) + { + if (item.Name.ToLower() == name.ToLower()) + { return item; } } @@ -209,14 +266,14 @@ namespace Falcon.StoredProcedureRunner /// 参数类型 /// 参数对象 /// 一个参数字符串。比如@p2=@p4,@p1=@p3 - 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(','); - } + //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(','); + //} } } diff --git a/src/Falcon.StoredProcedureRunnerTests/AppSettings.json b/src/Falcon.StoredProcedureRunnerTests/AppSettings.json new file mode 100644 index 0000000..607d373 --- /dev/null +++ b/src/Falcon.StoredProcedureRunnerTests/AppSettings.json @@ -0,0 +1,7 @@ +{ + "db": { + "ver": "11", + "oracle": "DATA SOURCE=(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST =47.103.62.60)(PORT = 1521)))(CONNECT_DATA = (SERVICE_NAME = orcl)));PASSWORD = harmonyhis;PERSIST SECURITY INFO = True;USER ID = HARMONYHIS;Connection Lifetime = 120;Connection Timeout = 60", + "sqlserver": "Server=.\\SQLSERVER2008R2;Database=test;User ID=sa;Password=111;" + } +} diff --git a/src/Falcon.StoredProcedureRunnerTests/Falcon.StoredProcedureRunnerTests.csproj b/src/Falcon.StoredProcedureRunnerTests/Falcon.StoredProcedureRunnerTests.csproj new file mode 100644 index 0000000..9175836 --- /dev/null +++ b/src/Falcon.StoredProcedureRunnerTests/Falcon.StoredProcedureRunnerTests.csproj @@ -0,0 +1,35 @@ + + + + net5.0 + enable + + false + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/src/Falcon.StoredProcedureRunnerTests/OracleModel.cs b/src/Falcon.StoredProcedureRunnerTests/OracleModel.cs new file mode 100644 index 0000000..f5e8a88 --- /dev/null +++ b/src/Falcon.StoredProcedureRunnerTests/OracleModel.cs @@ -0,0 +1,20 @@ +using Falcon.StoredProcedureRunner; +using System.Data; + +namespace Falcon.StoredProcedureRunnerTests +{ + internal class GetEmployee + { + public string v_orgaid { get; set; } + + [FalconSPPrarmDirection(ParameterDirection.Output)] + [FalconSPPrarmType(FalconSPDbType.OracleRefCursor)] + public object v_data { get; set; } + } + internal class GetEmployeeResult + { + public string empcode { get; set; } + public string empname { get; set; } + public string empactive { get; set; } + } +} diff --git a/src/Falcon.StoredProcedureRunnerTests/RunnerTests.cs b/src/Falcon.StoredProcedureRunnerTests/RunnerTests.cs new file mode 100644 index 0000000..1b7a50d --- /dev/null +++ b/src/Falcon.StoredProcedureRunnerTests/RunnerTests.cs @@ -0,0 +1,60 @@ +using Falcon.StoredProcedureRunnerTests; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Linq; + +namespace Falcon.StoredProcedureRunner.Tests +{ + [TestClass()] + public class RunnerTests + { + [TestMethod()] + public void RunTest() + { + OracleTest(); + SqlserverTest(); + } + + public void SqlserverTest() + { + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddJsonFile("AppSettings.json"); + 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 result = runner.Run(db, new SqlserverModel + { + p1 = 1, + p2 = 2, + p3 = "abc," + }).ToList(); + Assert.IsNotNull(result); + CollectionAssert.AllItemsAreNotNull(result); + Assert.IsTrue(result.Count > 0); + } + + public void OracleTest() + { + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddJsonFile("AppSettings.json"); + 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(db, new GetEmployee + { + v_orgaid = "50e3d44d-9ca2-4fbd-9d5d-d32339b1b113", + }).ToList(); + Assert.IsNotNull(result); + CollectionAssert.AllItemsAreNotNull(result); + Assert.IsTrue(result.Count > 0); + } + } +} \ No newline at end of file diff --git a/src/Falcon.StoredProcedureRunnerTests/SqlserverModel.cs b/src/Falcon.StoredProcedureRunnerTests/SqlserverModel.cs new file mode 100644 index 0000000..0238b04 --- /dev/null +++ b/src/Falcon.StoredProcedureRunnerTests/SqlserverModel.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Falcon.StoredProcedureRunnerTests +{ + [Falcon.StoredProcedureRunner.FalconSPProcuderName("TestSp1")] + public class SqlserverModel + { + public int p1 { get; set; } + public int p2 { get; set; } + public string p3 { get; set; } + } + + public class SqlserverModelResult + { + public double Id { get; set; } + public string s { get; set; } + public double jia { get; set; } + public double jian { get; set; } + public double chen { get; set; } + public double chu { get; set; } + } +}