diff --git a/.gitignore b/.gitignore index cd2946a..12c77d5 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,16 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk + +# Build results +[Dd]ebug/ +[Rr]elease/ +[Bb]in/ +[Oo]bj/ +[Oo]utput*/ +packages/ +# Visual Studio +.vs/ +_NCrunch*/ +*.ncrunchsolution +*.user diff --git a/OdpNetMicroMapper.nuspec b/OdpNetMicroMapper.nuspec deleted file mode 100644 index cb38079..0000000 --- a/OdpNetMicroMapper.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - OdpNetMicroMapper - 1.2 - OdpNetMicroMapper - Stig Christensen - BankInvest - http://www.bankinvest.dk - https://github.com/stigc/OdpNetMicroMapper - false - Easy and simple Oracle db mapper - - Copyright 2017 - odp.net oracle connection orm micro mapper - - - - - - - - diff --git a/OdpNetMicroMapper.sln b/OdpNetMicroMapper.sln index 959407a..b75d2b1 100644 --- a/OdpNetMicroMapper.sln +++ b/OdpNetMicroMapper.sln @@ -1,9 +1,15 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OdpNetMicroMapper", "OdpNetMicroMapper\OdpNetMicroMapper.csproj", "{A18AC73A-2B4B-4D66-BF15-1094CBEDCC1F}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OdpNetMicroMapper", "OdpNetMicroMapper\OdpNetMicroMapper.csproj", "{A18AC73A-2B4B-4D66-BF15-1094CBEDCC1F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{CC7CDBB4-E507-4558-A7DE-9800D19624D7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{CC7CDBB4-E507-4558-A7DE-9800D19624D7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestManagedCore", "TestManagedCore\TestManagedCore.csproj", "{E11DFADB-53F1-463A-AE18-5BC65C8EAD26}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestManaged", "TestManaged\TestManaged.csproj", "{A7BDAEAC-FB26-4BCA-AF89-A4C14C0E3A9B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,8 +25,19 @@ Global {CC7CDBB4-E507-4558-A7DE-9800D19624D7}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC7CDBB4-E507-4558-A7DE-9800D19624D7}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC7CDBB4-E507-4558-A7DE-9800D19624D7}.Release|Any CPU.Build.0 = Release|Any CPU + {E11DFADB-53F1-463A-AE18-5BC65C8EAD26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E11DFADB-53F1-463A-AE18-5BC65C8EAD26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E11DFADB-53F1-463A-AE18-5BC65C8EAD26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E11DFADB-53F1-463A-AE18-5BC65C8EAD26}.Release|Any CPU.Build.0 = Release|Any CPU + {A7BDAEAC-FB26-4BCA-AF89-A4C14C0E3A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7BDAEAC-FB26-4BCA-AF89-A4C14C0E3A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7BDAEAC-FB26-4BCA-AF89-A4C14C0E3A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7BDAEAC-FB26-4BCA-AF89-A4C14C0E3A9B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B4FE17EF-B531-4D60-B63F-F4980F422F8D} + EndGlobalSection EndGlobal diff --git a/OdpNetMicroMapper/Connection.cs b/OdpNetMicroMapper/Connection.cs index 45ae4b7..79f1cb8 100644 --- a/OdpNetMicroMapper/Connection.cs +++ b/OdpNetMicroMapper/Connection.cs @@ -5,41 +5,40 @@ namespace OdpNetMicroMapper { public class Connection : IDisposable { - int level = 0; - IDbConnection connection; - DbMapper orm; + private int _level; + private readonly IDbConnection _connection; + private readonly DbMapper _orm; public IDbConnection GetAdoConnection() { - return connection; + return _connection; } public Connection(DbMapper orm, IDbConnection connection) { - this.orm = orm; - this.connection = connection; + _orm = orm; + _connection = connection; } public void NextLevel() { - level++; + _level++; } public IDbTransaction BeginTransaction() { - return connection.BeginTransaction(); + return _connection.BeginTransaction(); } - public void Dispose() { - if (level == 0) + if (_level == 0) { - connection.Dispose(); - orm.ReleaseConnection(); + _connection.Dispose(); + _orm.ReleaseConnection(); } else { - level--; + _level--; } } } diff --git a/OdpNetMicroMapper/DbMapper.cs b/OdpNetMicroMapper/DbMapper.cs index 7fa9fce..9cb3c02 100644 --- a/OdpNetMicroMapper/DbMapper.cs +++ b/OdpNetMicroMapper/DbMapper.cs @@ -4,6 +4,7 @@ using System.Data; using System.Reflection; using System.Configuration; +using System.IO; namespace OdpNetMicroMapper { @@ -18,58 +19,83 @@ public class DbMapper public static volatile bool PrintSqls = false; public string ConnectionString { get; set; } - Type oracleConnectionType, oracleDataAdapterType; - Connection connectionWhenCreateExternal; - + private Type _oracleConnectionType, _oracleDataAdapterType, _oracleClobType; + private Connection _connectionWhenCreateExternal; + public DbMapper() { ConnectionString = ConfigurationManager.AppSettings["ConnectionString"]; + FindOracleDataTypes(); + } + - oracleDataAdapterType = TypeFromAssembly("Oracle.DataAccess.Client.OracleDataAdapter"); - oracleConnectionType = TypeFromAssembly("Oracle.DataAccess.Client.OracleConnection"); + private void FindOracleDataTypes() + { + var prefix = "Oracle.ManagedDataAccess"; + var assembly = FindDataAccessAssembly(prefix); + if (assembly == null) + { + prefix = "Oracle.DataAccess"; + assembly = FindDataAccessAssembly(prefix); + } + if (assembly == null) throw new FileNotFoundException($"Unable to load assembly {prefix}"); + + _oracleDataAdapterType = TypeFromAssembly(assembly, $"{prefix}.Client.OracleDataAdapter"); + _oracleConnectionType = TypeFromAssembly(assembly, $"{prefix}.Client.OracleConnection"); + _oracleClobType = TypeFromAssembly(assembly, $"{prefix}.Types.OracleClob"); } - private Type TypeFromAssembly(string typeAsString) + private Assembly FindDataAccessAssembly(string partialName) { - Assembly assembly = Assembly.Load("Oracle.DataAccess"); - Type type = assembly.GetType(typeAsString, false); + try + { + return Assembly.Load(partialName); + } + catch + { + return null; + } + } + + private Type TypeFromAssembly(Assembly assembly, string typeAsString) + { + var type = assembly.GetType(typeAsString, false); return type; } /// /// Use this to establish a SYSDBA connection /// - /// public void ConnectAsSys(string dataSource, string password) { - ConnectionString = String.Format("data source={0}; user id=sys; password={1}; dba privilege=sysdba", dataSource, password); + ConnectionString = string.Format("data source={0}; user id=sys; password={1}; dba privilege=sysdba", dataSource, password); } public Connection SetExternalConnection(IDbConnection connection) { - connectionWhenCreateExternal = CreateOrReuseConnection(connection); - return connectionWhenCreateExternal; + _connectionWhenCreateExternal = CreateOrReuseConnection(connection); + return _connectionWhenCreateExternal; } public Connection OpenConnection() { - if (connectionWhenCreateExternal != null) + if (_connectionWhenCreateExternal != null) throw new Exception("Cannot open new Connection. Already open"); - connectionWhenCreateExternal = CreateOrReuseConnection(); - return connectionWhenCreateExternal; + _connectionWhenCreateExternal = CreateOrReuseConnection(); + return _connectionWhenCreateExternal; } private Connection CreateOrReuseConnection(IDbConnection connection = null) { - if (connectionWhenCreateExternal != null) + if (_connectionWhenCreateExternal != null) { - connectionWhenCreateExternal.NextLevel(); - return connectionWhenCreateExternal; + _connectionWhenCreateExternal.NextLevel(); + return _connectionWhenCreateExternal; } if (connection == null) { - connection = (IDbConnection)Activator.CreateInstance(oracleConnectionType); + connection = (IDbConnection)Activator.CreateInstance(_oracleConnectionType); connection.ConnectionString = ConnectionString; connection.Open(); } @@ -78,19 +104,18 @@ private Connection CreateOrReuseConnection(IDbConnection connection = null) internal void ReleaseConnection() { - connectionWhenCreateExternal = null; + _connectionWhenCreateExternal = null; } public IDbDataAdapter CreateOracleDataAdapter() { - return (IDbDataAdapter)Activator.CreateInstance(oracleDataAdapterType); + return (IDbDataAdapter)Activator.CreateInstance(_oracleDataAdapterType); } public object CreateClob(string text, IDbConnection connection) { - var oracleClobType = TypeFromAssembly("Oracle.DataAccess.Types.OracleClob"); - object clob = Activator.CreateInstance(oracleClobType, new object[] { connection }); - MethodInfo method = oracleClobType.GetMethod("Append", new Type[] { typeof(char[]), typeof(int), typeof(int) }); + var clob = Activator.CreateInstance(_oracleClobType, connection); + var method = _oracleClobType.GetMethod("Append", new[] { typeof(char[]), typeof(int), typeof(int) }); method.Invoke(clob, new object[] { text.ToCharArray(), 0, text.Length }); return clob; } @@ -109,13 +134,13 @@ public IDbCommand CreateCommand(string sql, IDbConnection connection, bool bindB cmd.GetType().GetProperty("InitialLONGFetchSize") .SetValue(cmd, 1024 * 64, null); //reade up to 64kb with long columns - if (sql!=null) + if (sql != null) cmd.CommandText = sql; return cmd; } - private void SetParameter(IDbDataParameter parameter, object value, string columnName, IDbCommand cmd, Type type = null) + private void SetParameter(IDbDataParameter parameter, object value, IDbCommand cmd, Type type = null) { if (value == null) { @@ -176,22 +201,22 @@ private void SetParameter(IDbDataParameter parameter, object value, string colum public void Insert(object item, string dbName) { - Entity entity = item.ToEntity(); + var entity = item.ToEntity(); entity.TableName = dbName; Insert(entity); } public void Insert(Entity item) { - SqlTokens sqlTokens = new SqlTokens(item.GetDictionaryInDbStyle(true)); - string sql = "insert into " + item.TableName + var sqlTokens = new SqlTokens(item.GetDictionaryInDbStyle(true)); + var sql = "insert into " + item.TableName + " (" + sqlTokens.AsColumnNames(false) + ") select " + sqlTokens.AsIndcies(false) + " from dual"; using (var connection = CreateOrReuseConnection()) { using (var command = CreateCommand(sql, connection.GetAdoConnection())) { - AddParameters(command, sqlTokens.GetNonNullableFieldsAndValues(), connection.GetAdoConnection(), 0); + AddParameters(command, sqlTokens.GetNonNullableFieldsAndValues(), 0); command.ExecuteNonQuery(); } } @@ -201,11 +226,11 @@ public void MergeInto(Entity item) { var dic = item.GetWhereClauseOnPrimaryKeyDbStyle(); var args = dic.Values.ToArray(); - string whereClause = new SqlTokens(dic).AsWhereClause(); + var whereClause = new SqlTokens(dic).AsWhereClause(); - string sql = "select count(1) from " + item.TableName + " " + whereClause; + var sql = "select count(1) from " + item.TableName + " " + whereClause; - int count = QueryScalar(sql, args); + var count = QueryScalar(sql, args); if (count == 0) Insert(item); @@ -215,13 +240,13 @@ public void MergeInto(Entity item) private void AddParameters(IDbCommand cmd, object[] args) { - AddParameters(cmd, args.ToDictionary(x => Guid.NewGuid().ToString(), x => x), cmd.Connection, 0); + AddParameters(cmd, args.ToDictionary(x => Guid.NewGuid().ToString(), x => x), 0); } - private void AddParameters(IDbCommand cmd, IDictionary columnsAndValues, IDbConnection connection, int offset, bool useKeyNames = false) + private void AddParameters(IDbCommand cmd, IDictionary columnsAndValues, int offset, bool useKeyNames = false) { - int index = offset; - foreach (KeyValuePair o in columnsAndValues) + var index = offset; + foreach (var o in columnsAndValues) { var parameter = cmd.CreateParameter(); if (useKeyNames) @@ -230,7 +255,7 @@ private void AddParameters(IDbCommand cmd, IDictionary columnsAn parameter.ParameterName = index.ToString(); if (o.Key.EndsWith("Output")) parameter.Direction = ParameterDirection.Output; - SetParameter(parameter, o.Value, o.Key, cmd); + SetParameter(parameter, o.Value, cmd); cmd.Parameters.Add(parameter); index++; } @@ -242,12 +267,12 @@ public void Delete(Entity item, string whereClause = null, params object[] args) if (whereClause == null) { var dic = item.GetWhereClauseOnPrimaryKeyDbStyle(); - SqlTokens sqlTokens = new SqlTokens(dic); + var sqlTokens = new SqlTokens(dic); whereClause = sqlTokens.AsWhereClause(); args = dic.Values.ToArray(); } - string sql = "delete from " + item.TableName + " " + whereClause; + var sql = "delete from " + item.TableName + " " + whereClause; using (var connection = CreateOrReuseConnection()) { @@ -274,9 +299,9 @@ public void Update(Entity item, string whereClause = null, params object[] args) if (nonPrimaryKeysColumns.Count == 0) return; - SqlTokens setClauseTokens = new SqlTokens(nonPrimaryKeysColumns); + var setClauseTokens = new SqlTokens(nonPrimaryKeysColumns); - string sql = "update " + item.TableName + var sql = "update " + item.TableName + " " + setClauseTokens.AsSetClause(args.Length) + " " + whereClause; @@ -285,7 +310,7 @@ public void Update(Entity item, string whereClause = null, params object[] args) using (var command = CreateCommand(sql, connection.GetAdoConnection())) { AddParameters(command, args); - AddParameters(command, item.GetDictionaryInDbStyle(false), null, args.Length); + AddParameters(command, item.GetDictionaryInDbStyle(false), args.Length); command.ExecuteNonQuery(); } } @@ -298,11 +323,11 @@ public T QueryScalar(string sql, params object[] args) using (var command = CreateCommand(sql, connection.GetAdoConnection())) { AddParameters(command, args); - object result = command.ExecuteScalar(); + var result = command.ExecuteScalar(); - bool isString = typeof(T) == typeof(string); - bool isNullableType = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition(); + var isString = typeof(T) == typeof(string); + var isNullableType = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition(); //NULL handle if (isNullableType || isString) @@ -315,7 +340,7 @@ public T QueryScalar(string sql, params object[] args) if (isNullableType) { - Type type = Nullable.GetUnderlyingType(typeof(T)); + var type = Nullable.GetUnderlyingType(typeof(T)); return (T)Convert.ChangeType(result, type); } @@ -336,7 +361,7 @@ public void NonQueryIgnoreError(string sql, params object[] args) { command.ExecuteNonQuery(); } - catch(Exception ex) + catch (Exception ex) { Console.WriteLine("Db Exception ignored: " + ex.Message); } @@ -364,7 +389,7 @@ public void NonQuery(string sql, params object[] args) { AddParameters(command, args); - using (IDataReader reader = command.ExecuteReader()) + using (var reader = command.ExecuteReader()) { while (reader.Read()) { @@ -383,7 +408,7 @@ public IEnumerable Query(string sql, params object[] args) { AddParameters(command, args); - using (IDataReader reader = command.ExecuteReader()) + using (var reader = command.ExecuteReader()) { while (reader.Read()) { @@ -394,7 +419,7 @@ public IEnumerable Query(string sql, params object[] args) } } - public IEnumerable QuerySingleTypeList(string sql, params object[] args) + public IEnumerable QuerySingleTypeList(string sql, params object[] args) { using (var connection = CreateOrReuseConnection()) { @@ -402,7 +427,7 @@ public IEnumerable QuerySingleTypeList(string sql, params object[] args) { AddParameters(command, args); - using (IDataReader reader = command.ExecuteReader()) + using (var reader = command.ExecuteReader()) { while (reader.Read()) { @@ -425,13 +450,12 @@ public T ExecuteFunction(string functionName, params object[] args) { using (var cmd = CreateCommand(null, connection.GetAdoConnection(), false)) { - DataSet ds = new DataSet(); cmd.CommandText = functionName; cmd.CommandType = CommandType.StoredProcedure; //return value var parameter = cmd.CreateParameter(); - SetParameter(parameter, default(T), "dummy", cmd, typeof(T)); + SetParameter(parameter, default(T), cmd, typeof(T)); parameter.Direction = ParameterDirection.ReturnValue; cmd.Parameters.Add(parameter); @@ -449,21 +473,21 @@ public IEnumerable ExecuteProcedure(string procedureName, params object { using (var command = CreateCommand(null, connection.GetAdoConnection(), false)) { - DataSet ds = new DataSet(); + var ds = new DataSet(); command.CommandText = procedureName; command.CommandType = CommandType.StoredProcedure; AddParameters(command, args); //Execute - IDbDataAdapter da = CreateOracleDataAdapter(); + var da = CreateOracleDataAdapter(); da.SelectCommand = command; da.Fill(ds); - + if (ds.Tables.Count < 1) return null; - List list = new List(); - + var list = new List(); + foreach (DataRow row in ds.Tables[0].Rows) list.Add(row.ToEntity()); return list; @@ -475,6 +499,7 @@ public IEnumerable ExecuteProcedure(string procedureName, params object /// Set OracleDbType on a OracleParameter without a reference to Oracle DataAccess /// /// Clob, Blob etc. + /// public void SetParameterOracleDbType(IDbDataParameter parameter, string type) { var pOracleDbType = parameter.GetType().GetProperty("OracleDbType"); diff --git a/OdpNetMicroMapper/Entity.cs b/OdpNetMicroMapper/Entity.cs index b4d9c31..b923b80 100644 --- a/OdpNetMicroMapper/Entity.cs +++ b/OdpNetMicroMapper/Entity.cs @@ -7,40 +7,40 @@ namespace OdpNetMicroMapper { public class Entity : DynamicObject { - string dbPrimaryKey; + private readonly string _dbPrimaryKey; public string TableName { get; set; } - Dictionary dictionary = new Dictionary(); + private readonly Dictionary _dictionary = new Dictionary(); public Entity(Dictionary dictionary) { - this.dictionary = dictionary; + _dictionary = dictionary; } public Entity(string tableName, string dbPrimaryKey = null) { TableName = tableName; - this.dbPrimaryKey = dbPrimaryKey; + _dbPrimaryKey = dbPrimaryKey; } private bool IsPrimaryKey(string propertyName) { - if (dbPrimaryKey == null) + if (_dbPrimaryKey == null) return false; - return dbPrimaryKey.Split(new char[] { ',' }) + return _dbPrimaryKey.Split(new[] { ',' }) .Select(x => x.Trim()) .Contains(propertyName); } public IDictionary GetDictionary() { - return dictionary; + return _dictionary; } public Dictionary GetDictionaryInDbStyle(bool includePrimaryKey) { - Dictionary dic = new Dictionary(); - foreach (KeyValuePair element in dictionary) + var dic = new Dictionary(); + foreach (var element in _dictionary) if (includePrimaryKey || !IsPrimaryKey(element.Key.UnCammelCase())) dic.Add(element.Key.UnCammelCase(), element.Value); return dic; @@ -48,38 +48,38 @@ public Dictionary GetDictionaryInDbStyle(bool includePrimaryKey) public Dictionary GetWhereClauseOnPrimaryKeyDbStyle() { - if (dbPrimaryKey == null) + if (_dbPrimaryKey == null) throw new ApplicationException("Primary key is not set"); var dic = new Dictionary(); - foreach (string column in dbPrimaryKey.Split(new char[] { ',' })) + foreach (var column in _dbPrimaryKey.Split(new[] { ',' })) { - string domainProperty = column.Trim().CammelCase(); - if (!dictionary.ContainsKey(domainProperty)) + var domainProperty = column.Trim().CammelCase(); + if (!_dictionary.ContainsKey(domainProperty)) throw new ApplicationException("Property '" + domainProperty + "' was not found"); - dic.Add(column, dictionary[domainProperty]); + dic.Add(column, _dictionary[domainProperty]); } return dic; } public override bool TrySetMember(SetMemberBinder binder, object value) { - dictionary[binder.Name] = value; + _dictionary[binder.Name] = value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { - return dictionary.TryGetValue(binder.Name, out result); + return _dictionary.TryGetValue(binder.Name, out result); } public override string ToString() { - string s = ""; + var s = ""; - foreach (KeyValuePair element in dictionary) - s += element.Key + " = "+ element.Value + "\n"; + foreach (var element in _dictionary) + s += element.Key + " = " + element.Value + "\n"; return s; } diff --git a/OdpNetMicroMapper/ObjectExtensions.cs b/OdpNetMicroMapper/ObjectExtensions.cs index 40ee67f..aefd6e2 100644 --- a/OdpNetMicroMapper/ObjectExtensions.cs +++ b/OdpNetMicroMapper/ObjectExtensions.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Data; -using System.Reflection; using System.Collections; namespace OdpNetMicroMapper @@ -18,13 +17,13 @@ public static string RemoveInEnd(this string text, string search) public static string UnCammelCase(this string name) { - string s = ""; + var s = ""; - foreach (char c in name) + foreach (var c in name) { if (char.IsUpper(c) && s.Length>0) s += "_"; - s += Char.ToLower(c); + s += char.ToLower(c); } return s; @@ -44,12 +43,12 @@ private static bool IsUnderscoreAndIsReverseable(string columnName, int index) public static string CammelCase(this string name) { - string s = ""; - bool nextIsToUpper = true; + var s = ""; + var nextIsToUpper = true; - for (int i = 0; i < name.Length; i++) + for (var i = 0; i < name.Length; i++) { - char c = name[i]; + var c = name[i]; if (IsUnderscoreAndIsReverseable(name, i)) { @@ -97,7 +96,7 @@ public static Entity ToEntity(this object o) public static Entity ToEntity(this IDataReader rdr) { var dic = new Dictionary(); - for (int i = 0; i < rdr.FieldCount; i++) + for (var i = 0; i < rdr.FieldCount; i++) { try { @@ -121,19 +120,19 @@ public static Entity ToEntity(this DataRow row) public static T ToObject(this IDataReader rdr) where T : new() { - T o = new T(); - for (int i = 0; i < rdr.FieldCount; i++) + var o = new T(); + for (var i = 0; i < rdr.FieldCount; i++) { var name = rdr.GetName(i).CammelCase(); - PropertyInfo pi = o.GetType().GetProperty(name); + var pi = o.GetType().GetProperty(name); if (pi != null) { try { - Type type = Nullable.GetUnderlyingType(pi.PropertyType) + var type = Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType; - object value = DBNull.Value.Equals(rdr[i]) ? null : + var value = DBNull.Value.Equals(rdr[i]) ? null : Convert.ChangeType(rdr[i], type); pi.SetValue(o, value, null); diff --git a/OdpNetMicroMapper/OdpNetMicroMapper.csproj b/OdpNetMicroMapper/OdpNetMicroMapper.csproj index a070869..28a52ec 100644 --- a/OdpNetMicroMapper/OdpNetMicroMapper.csproj +++ b/OdpNetMicroMapper/OdpNetMicroMapper.csproj @@ -1,60 +1,34 @@ - - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {A18AC73A-2B4B-4D66-BF15-1094CBEDCC1F} - Library - Properties - OdpNetMicroMapper - OdpNetMicroMapper - v4.0 - 512 - - - true - full - false - ..\output\ - DEBUG;TRACE - prompt - 4 - AnyCPU - - - pdbonly - true - ..\output\ - TRACE - prompt - 4 + netcoreapp2.0;net461 + 2.0.0.0 + 2.0.0.0 + 2.0.0 + true + Stig Christensen, Michael Hjorth + BankInvest + Easy and simple Oracle db mapper + odp.net oracle connection orm micro mapper + BankInvest 2018 + Oracle driver must be added manually. Choose the relevant driver for your setup: +.net 4.6.1 edition supports managed driver from NuGet or unmanaged driver loaded from GAC. +.net core 2.0 edition supports managed driver only (currently only beta release available from Oracle). + + - - - - - + + - - + - - - - - - - + + + - - - \ No newline at end of file + + + + + diff --git a/OdpNetMicroMapper/Properties/AssemblyInfo.cs b/OdpNetMicroMapper/Properties/AssemblyInfo.cs deleted file mode 100644 index 8e3d98e..0000000 --- a/OdpNetMicroMapper/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("OdpNetMicroMapper")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("OdpNetMicroMapper")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("566e38b8-352d-4b3d-aa32-0f67f8426e30")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] diff --git a/OdpNetMicroMapper/SqlTokens.cs b/OdpNetMicroMapper/SqlTokens.cs index 5b19c6f..576b23f 100644 --- a/OdpNetMicroMapper/SqlTokens.cs +++ b/OdpNetMicroMapper/SqlTokens.cs @@ -3,25 +3,25 @@ namespace OdpNetMicroMapper { - class SqlTokens + public class SqlTokens { - IDictionary dic = new Dictionary(); + private readonly IDictionary _dic; public SqlTokens(IDictionary dic) { - this.dic = dic; + _dic = dic; } public IDictionary GetNonNullableFieldsAndValues() { - return dic.Where(x => x.Value != null) + return _dic.Where(x => x.Value != null) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } public string AsWhereClause(int index = 0) { string sql = ""; - foreach (string token in dic.Keys) + foreach (string token in _dic.Keys) { sql += token + "=:" + index + " and "; index++; @@ -32,14 +32,12 @@ public string AsWhereClause(int index = 0) public string AsColumnNames(bool includeNullFields = true) { - int index = 0; string sql = ""; - foreach (string token in dic.Keys) + foreach (string token in _dic.Keys) { - if (dic[token] != null || includeNullFields) + if (_dic[token] != null || includeNullFields) { sql += token.UnCammelCase() + ", "; - index++; } } sql = sql.RemoveInEnd(", "); @@ -50,9 +48,9 @@ public string AsIndcies(bool includeNullFields = true) { int index = 0; string sql = ""; - foreach (string token in dic.Keys) + foreach (string token in _dic.Keys) { - if (dic[token] != null || includeNullFields) + if (_dic[token] != null || includeNullFields) { sql += ":" + index + ", "; index++; @@ -65,7 +63,7 @@ public string AsIndcies(bool includeNullFields = true) public string AsSetClause(int index = 0) { string sql = "set "; - foreach (string token in dic.Keys) + foreach (string token in _dic.Keys) { sql += token + "=:" + index + ", "; index++; diff --git a/OdpNetMicroMapper/readme.txt b/OdpNetMicroMapper/readme.txt new file mode 100644 index 0000000..0208fad --- /dev/null +++ b/OdpNetMicroMapper/readme.txt @@ -0,0 +1,5 @@ +- No odp.net binary reference +- Supports select/insert/update/delete/procedures +- Supports Oracle procedures with RefCursor +- Supports dynamic Domain Model / static Domain Model +- Everything is one line of code. Even calls to Oracle procedures diff --git a/TestManaged/App.config b/TestManaged/App.config new file mode 100644 index 0000000..c17b27f --- /dev/null +++ b/TestManaged/App.config @@ -0,0 +1,33 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TestManaged/Test.cs b/TestManaged/Test.cs new file mode 100644 index 0000000..a30dbf8 --- /dev/null +++ b/TestManaged/Test.cs @@ -0,0 +1,589 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using NUnit.Framework; +using OdpNetMicroMapper; +using Oracle.ManagedDataAccess.Client; + +namespace TestManaged +{ + [TestFixture] + public class Test : TestBase + { + [Test] + public void InsertStatic() + { + Item item = new Item(); + item.Id = 3; + item.Name = "Third Item"; + orm.Insert(item, "onmm2.item"); + + item = orm.Query("select * from onmm2.item where id = :0", 3).SingleOrDefault(); + Assert.AreEqual(3, item.Id); + Assert.AreEqual("Third Item", item.Name); + Assert.AreEqual(DateTime.Today, item.DateValue.Value.Date); + } + + [Test] + public void RawTest() + { + var guid = new Guid(); + orm.NonQuery("insert into onmm2.rawtest (bytes) values (:0)", guid.ToByteArray()); + + var bytesLoaded = orm.QueryScalar("select bytes from onmm2.rawtest where rownum = 1"); + var guidLoaded = new Guid(bytesLoaded); + Assert.AreEqual(guid, guidLoaded); + + dynamic item = orm.Query("select bytes from onmm2.rawtest where rownum = 1").Single(); + Assert.AreEqual(guid, new Guid(item.Bytes)); + } + + [TestCase("double")] + [TestCase("float")] + [TestCase("decimal")] + public void InsertDynamicTest(string type) + { + dynamic item = new Entity("onmm2.item"); + item.Id = 3; + item.Name = "Third Item"; + item.DateValue = DateTime.Today; + if (type == "double") item.DecimalValue = 3.1415d; + if (type == "float") item.DecimalValue = 3.1415f; + if (type == "decimal") item.DecimalValue = 3.1415m; + + orm.Insert(item); + + item = orm.Query("select * from onmm2.item where id = :0", 3).Single(); + Assert.AreEqual(3, item.Id); + Assert.AreEqual(DateTime.Today, item.DateValue); + Assert.AreEqual("Third Item", item.Name); + Assert.AreEqual(DateTime.Today, item.DateValue.Date); + Assert.AreEqual(3.1415m, item.DecimalValue); + } + + [Test] + public void UpdateDynamicWithNull() + { + dynamic item = new Entity("onmm2.item", "id"); + item.Id = 1; + item.Name = null; + + orm.Update(item); + + item = orm.Query("select * from onmm2.item where id = :0", 1).Single(); + Assert.AreEqual(1, item.Id); + Assert.IsNull(item.Name); + } + + [Test] + public void InsertWithLongColumnMax4000chars() + { + dynamic item = new Entity("onmm2.item_with_long"); + item.Text = new string('X', 1000 * 4); //max 4k when inserting! + orm.Insert(item); + + var items = orm.Query("select * from onmm2.item_with_long"); + Assert.AreEqual(item.Text, items.Single().Text); + } + + [Test] + public void DeleteWithWhereClause() + { + dynamic item = new Entity("onmm2.item"); + Assert.AreEqual(2, orm.QueryScalar("select count(1) from onmm2.item")); + + orm.Delete(item, "where id = :0", 1); + Assert.AreEqual(1, orm.QueryScalar("select count(1) from onmm2.item")); + + orm.Delete(item, "where id = :0", 2); + Assert.AreEqual(0, orm.QueryScalar("select count(1) from onmm2.item")); + } + + [Test] + public void DeleteWithKeyMetadata() + { + dynamic item = new Entity("onmm2.item", "id"); + item.Id = 2; + Assert.AreEqual(2, orm.QueryScalar("select count(1) from onmm2.item")); + + orm.Delete(item); + Assert.AreEqual(1, orm.QueryScalar("select count(1) from onmm2.item")); + + //check that the existing element is not the one deleted. + var items = orm.Query("select * from onmm2.item"); + Assert.AreEqual(1, items.Single().Id); + } + + [Test] + public void QueryScalarWhenNoRows() + { + Assert.AreEqual(null, orm.QueryScalar("select 1 from onmm2.item where 1=2")); + } + + [Test] + public void QueryScalarNullable() + { + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + } + + [Test] + public void QueryScalar() + { + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual("1", orm.QueryScalar("select 1 from dual")); + + Assert.AreEqual(DateTime.Today, orm.QueryScalar("select trunc(sysdate) from dual")); + Assert.AreEqual("test", orm.QueryScalar("select 'test' from dual")); + Assert.AreEqual(1.123456789m, orm.QueryScalar("select 1.123456789 from dual")); + } + + [Test] + public void UpdateViaWhereClause() + { + dynamic item = new Entity("onmm2.item"); + item.Name = "RENAMED"; + orm.Update(item, "where id = :0", 1); + + var items = orm.Query("select id, name from onmm2.item order by id"); + Assert.AreEqual(items.First().Name, item.Name); + Assert.AreNotEqual(items.Last().Name, item.Name); + } + + [Test] + public void UpdateViaMetaData() + { + dynamic item = new Entity("onmm2.item", "id"); + item.Id = 1; + item.Name = "RENAMED"; + orm.Update(item); + + var items = orm.Query("select id, name from onmm2.item order by id"); + Assert.AreEqual(items.First().Name, item.Name); + Assert.AreNotEqual(items.Last().Name, item.Name); + } + + [Test] + public void MergeInto() + { + dynamic item = new Entity("onmm2.item", "id"); + item.Id = 100; + item.Name = "Name100"; + orm.MergeInto(item); + + var itemLoaded = orm.Query("select * from onmm2.item where id = :0", 100).SingleOrDefault(); + Assert.AreEqual(item.Name, itemLoaded.Name); + + item.Name = "renamed"; + orm.MergeInto(item); + + itemLoaded = orm.Query("select * from onmm2.item where id = :0", 100).SingleOrDefault(); + Assert.AreEqual(item.Name, itemLoaded.Name); + } + + [Test] + public void MergeIntoWithOnlyPrimaryKey_ShouldNotTryUpdateAndFail() + { + dynamic item = new Entity("onmm2.item", "id"); + item.Id = 100; + orm.MergeInto(item); + orm.MergeInto(item); + } + + [Test] + public void ColumnWithUnderScoreBeforeDigit() + { + Entity item = orm.Query("select yield_2date from onmm2.item_odd where id = 1").Single(); + + //Assert.AreEqual(99m, item.Yield_2date); + + foreach (var p in item.GetDictionaryInDbStyle(true)) + Assert.AreEqual("yield_2date", p.Key); + + foreach (var p in item.GetDictionary()) + Assert.AreEqual("Yield_2date", p.Key); + } + + + [Test] + public void QueryDynamicToString() + { + var item = orm.Query("select * from onmm2.item where id = 1").Single(); + Assert.That(item.ToString(), Contains.Substring("Id = 1")); + Assert.That(item.ToString(), Contains.Substring("Name = First Item")); + } + + [Test] + public void QuerySingleTypeList() + { + var ints = orm.QuerySingleTypeList("select id from onmm2.item order by id").ToList(); + Assert.AreEqual(1, ints[0]); + Assert.AreEqual(2, ints[1]); + + var strings = orm.QuerySingleTypeList("select name from onmm2.item order by id").ToList(); + Assert.AreEqual("First Item", strings[0]); + Assert.AreEqual("Second Item", strings[1]); + } + + [Test] + public void QueryStaticNoWhereClause() + { + var items = orm.Query("select * from onmm2.item order by id").ToList(); + Assert.AreEqual(2, items.Count); + Assert.AreEqual(1, items[0].Id); + Assert.AreEqual(2, items[1].Id); + Assert.AreEqual("First Item", items[0].Name); + Assert.AreEqual("Second Item", items[1].Name); + Assert.AreEqual(0.321m, items[0].DecimalValue); + Assert.AreEqual(.123m, items[1].DecimalValue); + } + + [Test] + public void QueryDynamicWithWhereClause() + { + var item = orm.Query("select id, name from onmm2.item where id = :0", 1).SingleOrDefault(); + Assert.AreEqual(1, item.Id); + Assert.AreEqual("First Item", item.Name); + } + + [Test] + public void QueryStaticWithWhereClause() + { + var item = orm.Query("select id, name from onmm2.item where id = :0", 1) + .SingleOrDefault(); + Assert.AreEqual(1, item.Id); + Assert.AreEqual("First Item", item.Name); + } + + [Test] + public void QueryNonExisting() + { + var item = orm.Query("select id, name from onmm2.item where id = :0", -1) + .SingleOrDefault(); + Assert.IsNull(item); + } + + + [Test] + public void ExecuteFunctionWithInt() + { + var result = orm.ExecuteFunction("onmm2.plus1function", 100); + Assert.AreEqual(101, result); + } + + [Test] + public void ExecuteFunctionWithString() + { + var result = orm.ExecuteFunction("onmm2.append1function", "100"); + Assert.AreEqual("1001", result); + } + + [Test] + public void ExecuteProcedureWithRefCursor() + { + var item = orm.ExecuteProcedure("onmm2.get_items_by_name", "First Item", DbMapperParameter.RefCursor) + .SingleOrDefault(); + Assert.AreEqual(1, item.Id); + Assert.AreEqual("First Item", item.Name); + } + + [Test] + public void ExecuteProcedureWithRefCursorZeroElements() + { + var items = orm.ExecuteProcedure("onmm2.get_items_by_name", "non existing", DbMapperParameter.RefCursor); + Assert.AreEqual(0, items.Count()); + } + + [Test] + public void ExecuteProcedureWithoutRefCursor() + { + string newName = "RENAMED"; + object result = orm.ExecuteProcedure("onmm2.rename_item", 1, newName); + Assert.IsNull(result); + Assert.AreEqual(newName, orm.QueryScalar("select name from onmm2.item where id = :0", 1)); + } + + [Test] + public void InsertWithImplicitConnection() + { + var sw = new Stopwatch(); + sw.Start(); + + int count = 1000; + dynamic item = new Entity("onmm2.item", "id"); + item.id = 1; + + for (int i = 0; i < count; i++) + orm.Insert(item); + + Assert.AreEqual(count + 2, orm.QueryScalar("select count(1) from onmm2.item")); + Console.WriteLine("InsertWithImplicitConnection Ms used: " + sw.ElapsedMilliseconds); + } + + [Test] + public void InsertWithExplicitConnection() + { + var sw = new Stopwatch(); + sw.Start(); + + int count = 1000; + dynamic item = new Entity("onmm2.item", "id"); + item.id = 1; + + using (var connection = orm.OpenConnection()) + { + for (int i = 0; i < count; i++) + orm.Insert(item); + } + + Assert.AreEqual(count + 2, orm.QueryScalar("select count(1) from onmm2.item")); + Console.WriteLine("InsertWithExplicitConnection Ms used: " + sw.ElapsedMilliseconds); + } + + [Test] + public void InsertWithExplicitConnectionAndTransaction() + { + var sw = new Stopwatch(); + sw.Start(); + + int count = 1000; + dynamic item = new Entity("onmm2.item", "id"); + item.id = 1; + + using (var connection = orm.OpenConnection()) + using (var tx = connection.BeginTransaction()) + { + for (int i = 0; i < count; i++) + orm.Insert(item); + tx.Commit(); + } + + Assert.AreEqual(count + 2, orm.QueryScalar("select count(1) from onmm2.item")); + Console.WriteLine("InsertWithExplicitConnectionAndTransaction Ms used: " + sw.ElapsedMilliseconds); + } + + [Test] + public void InsertAndSelectBigClob() + { + //this is at least 5 MB + string largeString = new string('X', 1024 * 1024 * 5); + + //insert + dynamic item = new Entity("onmm2.bigclobtest"); + item.Text = largeString; + orm.Insert(item); + + //select + item = orm.Query("select * from onmm2.bigclobtest").SingleOrDefault(); + Assert.AreEqual(largeString, item.Text); + + //scalar + string largeStringFetched = orm.QueryScalar("select text from onmm2.bigclobtest"); + Assert.AreEqual(largeString, largeStringFetched); + } + + + [Test] + public void InsertBigClobWithNonQuery() + { + //this is at least 5 MB + string largeString = new string('X', 1024 * 1024 * 5); + + orm.NonQuery("insert into onmm2.bigclobtest (text) values (:0)", largeString); + + string largeStringFetched = orm.QueryScalar("select text from onmm2.bigclobtest"); + Assert.AreEqual(largeString, largeStringFetched); + } + + [Test] + public void SelectWithExternalConnection() + { + Console.WriteLine("InsertWithExternalConnectionAndSelectBigClob"); + + using (OracleConnection oracleConnection = new OracleConnection(orm.ConnectionString)) + { + oracleConnection.Open(); + using (var conncetion = orm.SetExternalConnection(oracleConnection)) + { + var r = orm.QueryScalar("select 1 from dual"); + Assert.AreEqual(1, r); + } + } + } + + [Test] + public void InsertWithExternalConnectionAndSelectBigClob() + { + Console.WriteLine("InsertWithExternalConnectionAndSelectBigClob"); + + using (OracleConnection oracleConnection = new OracleConnection(orm.ConnectionString)) + { + oracleConnection.Open(); + using (var conncetion = orm.SetExternalConnection(oracleConnection)) + { + //this is at least 5 MB + string largeString = new string('X', 1024 * 1024 * 1); + + //insert + dynamic item = new Entity("onmm2.bigclobtest"); + item.Text = largeString; + orm.Insert(item); + + //select + item = orm.Query("select * from onmm2.bigclobtest").SingleOrDefault(); + Assert.AreEqual(largeString, item.Text); + + //scalar + string largeStringFetched = orm.QueryScalar("select text from onmm2.bigclobtest"); + Assert.AreEqual(largeString, largeStringFetched); + } + } + } + + [Test] + public void DeleteWithCompositeKeyt() + { + dynamic item1 = new Entity("onmm2.item_composite_key", "id, type"); + item1.Id = 1; + item1.Type = 1; + orm.Insert(item1); + + dynamic item2 = new Entity("onmm2.item_composite_key", "id,type"); + item2.Id = 1; + item2.Type = 2; + orm.Insert(item2); + + orm.Delete(item1); + var list = orm.Query("select * from onmm2.item_composite_key"); + Assert.AreEqual(2, list.Single().Type); + + orm.Delete(item2); + Assert.AreEqual(0, orm.QueryScalar("select count(1) from onmm2.item_composite_key")); + } + + [Test] + public void OverflowDynamic() + { + Assert.Throws(() => orm.Query("select 1/3 decimal_value from dual").Single()); + Assert.Throws(() => orm.Query("select 999999999999999999999999999999 decimal_value from dual").Single()); + } + + [Test] + public void Overflow() + { + Assert.Throws(() => orm.Query("select 1/3 decimal_value from dual").Single()); + Assert.Throws(() => orm.Query("select 999999999999999999999999999999 decimal_value from dual").Single()); + } + + [Test] + public void LoadStaticShouldWarn() + { + DbMapper.PrintWarnings = true; + DbMapper.PrintSqls = true; + var item = orm.Query("select id, name, decimal_value, date_value from onmm2.item where id = :0", 1).SingleOrDefault(); + DbMapper.PrintWarnings = false; + DbMapper.PrintSqls = false; + } + + [Test] + public void CollectionShouldNotBeUsed() + { + ItemWithCollection item = new ItemWithCollection(); + item.Id = 3; + item.GroupsNotPresentInDb = new List() { 1 }; + orm.Insert(item, "onmm2.item"); + } + + [Test] + public void ConnectAsSys() + { + var orm = new DbMapper(); + orm.ConnectAsSys("tstdaily", "bi"); + orm.QueryScalar("select 1 from dual"); + } + + [TestCase("1\n2")] + [TestCase("1\r\n2")] + [TestCase("1\n\r2")] + [TestCase("1\r2")] + public void ClobTests(string testValue) + { + dynamic item = new Entity("onmm2.bigclobtest"); + item.Text = testValue; + orm.Insert(item); + + var fromDb = orm.QueryScalar("select text from onmm2.bigclobtest"); + Assert.AreEqual(testValue, fromDb); + } + + [Test] + public void NonQueryIgnoreErrorShouldWork() + { + orm.NonQueryIgnoreError("should not work"); + } + + [Test] + public void ToEntityShouldIgnoreListProperties() + { + var entity = new SomeClass() + .ToEntity(); + + var dic = entity.GetDictionary(); + + Assert.AreEqual(4, dic.Count); + Assert.IsTrue(dic.ContainsKey("Prop1")); + Assert.IsTrue(dic.ContainsKey("Prop2")); + Assert.IsTrue(dic.ContainsKey("Prop3")); + Assert.IsTrue(dic.ContainsKey("Prop4")); + + } + } + + class ProcParameters + { + public decimal Input { get; set; } + public decimal EchoOutput { get; set; } + public decimal CountOutput { get; set; } + public object FundsOutput { get; set; } + } + + public class Item + { + public int Id { get; set; } + public string Name { get; set; } + public decimal DecimalValue { get; set; } + public DateTime? DateValue { get; set; } + } + + public class ItemWithCollection + { + public int Id { get; set; } + public List GroupsNotPresentInDb { get; set; } + } + + public class ItemWrongDefinition + { + public int Id { get; set; } + public string Name { get; set; } + public decimal Decimalvalue { get; set; } + public DateTime? Datevalue { get; set; } + } + + class SomeClass + { + public string Prop1 { get; set; } + public decimal Prop2 { get; set; } + public DateTime Prop3 { get; set; } + public int? Prop4 { get; set; } + public List Col1 { get; set; } + public String[] Col2 { get; set; } + public Dictionary Col3 { get; set; } + } +} diff --git a/TestManaged/TestBase.cs b/TestManaged/TestBase.cs new file mode 100644 index 0000000..3332aee --- /dev/null +++ b/TestManaged/TestBase.cs @@ -0,0 +1,124 @@ +using System; +using NUnit.Framework; +using OdpNetMicroMapper; + +namespace TestManaged +{ + [TestFixture] + public class TestBase + { + static bool firstRun = true; + protected DbMapper orm = new DbMapper(); + protected DbMapper sysOrm = new DbMapper(); + + private void CreateUser() + { + if (!firstRun) + return; + + firstRun = false; + + sysOrm.NonQueryIgnoreError("drop user onmm2 cascade"); + sysOrm.NonQuery("create user onmm2 identified by onmm2"); + sysOrm.NonQuery("grant create session to onmm2"); + sysOrm.NonQuery("alter user onmm2 quota unlimited on users"); + Console.WriteLine("user onmm2 created"); + + var sql = "create table onmm2.bigclobtest (text clob)"; + sysOrm.NonQuery(sql); + + sql = "create table onmm2.rawtest (bytes raw(16))"; + sysOrm.NonQuery(sql); + + sql = "create table onmm2.item_with_long (text long)"; + sysOrm.NonQuery(sql); + + sql = @"create table onmm2.item_odd (id number(10) not null, yield_2date number)"; + sysOrm.NonQuery(sql); + + sql = @"create table onmm2.item_composite_key (id number(10) not null, type number(10) not null, text varchar2(100))"; + sysOrm.NonQuery(sql); + + sql = @"create table onmm2.item (id number(10) not null, name varchar2(100), decimal_value number, date_value timestamp default sysdate not null)"; + sysOrm.NonQuery(sql); + + sql = @"create sequence onmm2.seq_items start with 3"; + sysOrm.NonQuery(sql); + + sql = @"create or replace function onmm2.append1function (pString varchar2) return varchar2 + as + begin + return pString || '1'; + end;"; + //todo fix elsewhere? //http://boncode.blogspot.com/2009/03/oracle-pls-00103-encountered-symbol.html + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace function onmm2.plus1function (pNumber number) return integer + as + begin + return pNumber + 1; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace procedure onmm2.get_items_by_name(pName in varchar2, io_cursor out SYS_REFCURSOR) is + begin + open io_cursor for + select * from onmm2.item t where t.name = pName; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace procedure onmm2.rename_item(pId number, pName in varchar2) is + begin + update onmm2.item t set t.name = pName where t.id = pId; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace procedure onmm2.proc_with_many_out_parameters(pInput number, pEcho out number, pCount out number, io_cursor out SYS_REFCURSOR) is + begin + select pInput into pEcho from dual; + select count(1) into pCount from onmm2.fund; + open io_cursor for + select * from onmm2.fund; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + } + + [TearDown] + public void DropSchema() + { + } + + [SetUp] + public void CreateSchema() + { + //throw new Exception("Please set 'data source' and 'password' in function CreateSchema()"); + + sysOrm.ConnectAsSys("INTSHARE", "bi"); + orm.ConnectionString = "data source=INTSHARE;user id=onmm2;password=onmm2;"; + + CreateUser(); + + sysOrm.NonQuery("delete from onmm2.item_composite_key"); + sysOrm.NonQuery("delete from onmm2.item"); + sysOrm.NonQuery("delete from onmm2.bigclobtest"); + sysOrm.NonQuery("delete from onmm2.item_with_long"); + sysOrm.NonQuery("delete from onmm2.item_odd"); + sysOrm.NonQuery("delete from onmm2.rawtest"); + + var sql = "insert into onmm2.item_odd (id, yield_2date) values (1, 99)"; + sysOrm.NonQuery(sql); + + sql = "insert into onmm2.item (id, name, decimal_value) values (1, 'First Item', 0.321)"; + sysOrm.NonQuery(sql); + + sql = "insert into onmm2.item (id, name, decimal_value) values (2, 'Second Item', 0.123)"; + sysOrm.NonQuery(sql); + + } + } +} diff --git a/TestManaged/TestManaged.csproj b/TestManaged/TestManaged.csproj new file mode 100644 index 0000000..e16ff03 --- /dev/null +++ b/TestManaged/TestManaged.csproj @@ -0,0 +1,17 @@ + + + + net461 + + + + + + + + + + + + + diff --git a/TestManagedCore/App.config b/TestManagedCore/App.config new file mode 100644 index 0000000..c17b27f --- /dev/null +++ b/TestManagedCore/App.config @@ -0,0 +1,33 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TestManagedCore/Test.cs b/TestManagedCore/Test.cs new file mode 100644 index 0000000..179a55a --- /dev/null +++ b/TestManagedCore/Test.cs @@ -0,0 +1,589 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using NUnit.Framework; +using OdpNetMicroMapper; +using Oracle.ManagedDataAccess.Client; + +namespace TestManagedCore +{ + [TestFixture] + public class Test : TestBase + { + [Test] + public void InsertStatic() + { + Item item = new Item(); + item.Id = 3; + item.Name = "Third Item"; + orm.Insert(item, "onmm3.item"); + + item = orm.Query("select * from onmm3.item where id = :0", 3).SingleOrDefault(); + Assert.AreEqual(3, item.Id); + Assert.AreEqual("Third Item", item.Name); + Assert.AreEqual(DateTime.Today, item.DateValue.Value.Date); + } + + [Test] + public void RawTest() + { + var guid = new Guid(); + orm.NonQuery("insert into onmm3.rawtest (bytes) values (:0)", guid.ToByteArray()); + + var bytesLoaded = orm.QueryScalar("select bytes from onmm3.rawtest where rownum = 1"); + var guidLoaded = new Guid(bytesLoaded); + Assert.AreEqual(guid, guidLoaded); + + dynamic item = orm.Query("select bytes from onmm3.rawtest where rownum = 1").Single(); + Assert.AreEqual(guid, new Guid(item.Bytes)); + } + + [TestCase("double")] + [TestCase("float")] + [TestCase("decimal")] + public void InsertDynamicTest(string type) + { + dynamic item = new Entity("onmm3.item"); + item.Id = 3; + item.Name = "Third Item"; + item.DateValue = DateTime.Today; + if (type == "double") item.DecimalValue = 3.1415d; + if (type == "float") item.DecimalValue = 3.1415f; + if (type == "decimal") item.DecimalValue = 3.1415m; + + orm.Insert(item); + + item = orm.Query("select * from onmm3.item where id = :0", 3).Single(); + Assert.AreEqual(3, item.Id); + Assert.AreEqual(DateTime.Today, item.DateValue); + Assert.AreEqual("Third Item", item.Name); + Assert.AreEqual(DateTime.Today, item.DateValue.Date); + Assert.AreEqual(3.1415m, item.DecimalValue); + } + + [Test] + public void UpdateDynamicWithNull() + { + dynamic item = new Entity("onmm3.item", "id"); + item.Id = 1; + item.Name = null; + + orm.Update(item); + + item = orm.Query("select * from onmm3.item where id = :0", 1).Single(); + Assert.AreEqual(1, item.Id); + Assert.IsNull(item.Name); + } + + [Test] + public void InsertWithLongColumnMax4000chars() + { + dynamic item = new Entity("onmm3.item_with_long"); + item.Text = new string('X', 1000 * 4); //max 4k when inserting! + orm.Insert(item); + + var items = orm.Query("select * from onmm3.item_with_long"); + Assert.AreEqual(item.Text, items.Single().Text); + } + + [Test] + public void DeleteWithWhereClause() + { + dynamic item = new Entity("onmm3.item"); + Assert.AreEqual(2, orm.QueryScalar("select count(1) from onmm3.item")); + + orm.Delete(item, "where id = :0", 1); + Assert.AreEqual(1, orm.QueryScalar("select count(1) from onmm3.item")); + + orm.Delete(item, "where id = :0", 2); + Assert.AreEqual(0, orm.QueryScalar("select count(1) from onmm3.item")); + } + + [Test] + public void DeleteWithKeyMetadata() + { + dynamic item = new Entity("onmm3.item", "id"); + item.Id = 2; + Assert.AreEqual(2, orm.QueryScalar("select count(1) from onmm3.item")); + + orm.Delete(item); + Assert.AreEqual(1, orm.QueryScalar("select count(1) from onmm3.item")); + + //check that the existing element is not the one deleted. + var items = orm.Query("select * from onmm3.item"); + Assert.AreEqual(1, items.Single().Id); + } + + [Test] + public void QueryScalarWhenNoRows() + { + Assert.AreEqual(null, orm.QueryScalar("select 1 from onmm3.item where 1=2")); + } + + [Test] + public void QueryScalarNullable() + { + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + Assert.AreEqual(null, orm.QueryScalar("select null from dual")); + } + + [Test] + public void QueryScalar() + { + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual(1, orm.QueryScalar("select 1 from dual")); + Assert.AreEqual("1", orm.QueryScalar("select 1 from dual")); + + Assert.AreEqual(DateTime.Today, orm.QueryScalar("select trunc(sysdate) from dual")); + Assert.AreEqual("test", orm.QueryScalar("select 'test' from dual")); + Assert.AreEqual(1.123456789m, orm.QueryScalar("select 1.123456789 from dual")); + } + + [Test] + public void UpdateViaWhereClause() + { + dynamic item = new Entity("onmm3.item"); + item.Name = "RENAMED"; + orm.Update(item, "where id = :0", 1); + + var items = orm.Query("select id, name from onmm3.item order by id"); + Assert.AreEqual(items.First().Name, item.Name); + Assert.AreNotEqual(items.Last().Name, item.Name); + } + + [Test] + public void UpdateViaMetaData() + { + dynamic item = new Entity("onmm3.item", "id"); + item.Id = 1; + item.Name = "RENAMED"; + orm.Update(item); + + var items = orm.Query("select id, name from onmm3.item order by id"); + Assert.AreEqual(items.First().Name, item.Name); + Assert.AreNotEqual(items.Last().Name, item.Name); + } + + [Test] + public void MergeInto() + { + dynamic item = new Entity("onmm3.item", "id"); + item.Id = 100; + item.Name = "Name100"; + orm.MergeInto(item); + + var itemLoaded = orm.Query("select * from onmm3.item where id = :0", 100).SingleOrDefault(); + Assert.AreEqual(item.Name, itemLoaded.Name); + + item.Name = "renamed"; + orm.MergeInto(item); + + itemLoaded = orm.Query("select * from onmm3.item where id = :0", 100).SingleOrDefault(); + Assert.AreEqual(item.Name, itemLoaded.Name); + } + + [Test] + public void MergeIntoWithOnlyPrimaryKey_ShouldNotTryUpdateAndFail() + { + dynamic item = new Entity("onmm3.item", "id"); + item.Id = 100; + orm.MergeInto(item); + orm.MergeInto(item); + } + + [Test] + public void ColumnWithUnderScoreBeforeDigit() + { + Entity item = orm.Query("select yield_2date from onmm3.item_odd where id = 1").Single(); + + //Assert.AreEqual(99m, item.Yield_2date); + + foreach (var p in item.GetDictionaryInDbStyle(true)) + Assert.AreEqual("yield_2date", p.Key); + + foreach (var p in item.GetDictionary()) + Assert.AreEqual("Yield_2date", p.Key); + } + + + [Test] + public void QueryDynamicToString() + { + var item = orm.Query("select * from onmm3.item where id = 1").Single(); + Assert.That(item.ToString(), Contains.Substring("Id = 1")); + Assert.That(item.ToString(), Contains.Substring("Name = First Item")); + } + + [Test] + public void QuerySingleTypeList() + { + var ints = orm.QuerySingleTypeList("select id from onmm3.item order by id").ToList(); + Assert.AreEqual(1, ints[0]); + Assert.AreEqual(2, ints[1]); + + var strings = orm.QuerySingleTypeList("select name from onmm3.item order by id").ToList(); + Assert.AreEqual("First Item", strings[0]); + Assert.AreEqual("Second Item", strings[1]); + } + + [Test] + public void QueryStaticNoWhereClause() + { + var items = orm.Query("select * from onmm3.item order by id").ToList(); + Assert.AreEqual(2, items.Count); + Assert.AreEqual(1, items[0].Id); + Assert.AreEqual(2, items[1].Id); + Assert.AreEqual("First Item", items[0].Name); + Assert.AreEqual("Second Item", items[1].Name); + Assert.AreEqual(0.321m, items[0].DecimalValue); + Assert.AreEqual(.123m, items[1].DecimalValue); + } + + [Test] + public void QueryDynamicWithWhereClause() + { + var item = orm.Query("select id, name from onmm3.item where id = :0", 1).SingleOrDefault(); + Assert.AreEqual(1, item.Id); + Assert.AreEqual("First Item", item.Name); + } + + [Test] + public void QueryStaticWithWhereClause() + { + var item = orm.Query("select id, name from onmm3.item where id = :0", 1) + .SingleOrDefault(); + Assert.AreEqual(1, item.Id); + Assert.AreEqual("First Item", item.Name); + } + + [Test] + public void QueryNonExisting() + { + var item = orm.Query("select id, name from onmm3.item where id = :0", -1) + .SingleOrDefault(); + Assert.IsNull(item); + } + + + [Test] + public void ExecuteFunctionWithInt() + { + var result = orm.ExecuteFunction("onmm3.plus1function", 100); + Assert.AreEqual(101, result); + } + + [Test] + public void ExecuteFunctionWithString() + { + var result = orm.ExecuteFunction("onmm3.append1function", "100"); + Assert.AreEqual("1001", result); + } + + [Test] + public void ExecuteProcedureWithRefCursor() + { + var item = orm.ExecuteProcedure("onmm3.get_items_by_name", "First Item", DbMapperParameter.RefCursor) + .SingleOrDefault(); + Assert.AreEqual(1, item.Id); + Assert.AreEqual("First Item", item.Name); + } + + [Test] + public void ExecuteProcedureWithRefCursorZeroElements() + { + var items = orm.ExecuteProcedure("onmm3.get_items_by_name", "non existing", DbMapperParameter.RefCursor); + Assert.AreEqual(0, items.Count()); + } + + [Test] + public void ExecuteProcedureWithoutRefCursor() + { + string newName = "RENAMED"; + object result = orm.ExecuteProcedure("onmm3.rename_item", 1, newName); + Assert.IsNull(result); + Assert.AreEqual(newName, orm.QueryScalar("select name from onmm3.item where id = :0", 1)); + } + + [Test] + public void InsertWithImplicitConnection() + { + var sw = new Stopwatch(); + sw.Start(); + + int count = 1000; + dynamic item = new Entity("onmm3.item", "id"); + item.id = 1; + + for (int i = 0; i < count; i++) + orm.Insert(item); + + Assert.AreEqual(count + 2, orm.QueryScalar("select count(1) from onmm3.item")); + Console.WriteLine("InsertWithImplicitConnection Ms used: " + sw.ElapsedMilliseconds); + } + + [Test] + public void InsertWithExplicitConnection() + { + var sw = new Stopwatch(); + sw.Start(); + + int count = 1000; + dynamic item = new Entity("onmm3.item", "id"); + item.id = 1; + + using (var connection = orm.OpenConnection()) + { + for (int i = 0; i < count; i++) + orm.Insert(item); + } + + Assert.AreEqual(count + 2, orm.QueryScalar("select count(1) from onmm3.item")); + Console.WriteLine("InsertWithExplicitConnection Ms used: " + sw.ElapsedMilliseconds); + } + + [Test] + public void InsertWithExplicitConnectionAndTransaction() + { + var sw = new Stopwatch(); + sw.Start(); + + int count = 1000; + dynamic item = new Entity("onmm3.item", "id"); + item.id = 1; + + using (var connection = orm.OpenConnection()) + using (var tx = connection.BeginTransaction()) + { + for (int i = 0; i < count; i++) + orm.Insert(item); + tx.Commit(); + } + + Assert.AreEqual(count + 2, orm.QueryScalar("select count(1) from onmm3.item")); + Console.WriteLine("InsertWithExplicitConnectionAndTransaction Ms used: " + sw.ElapsedMilliseconds); + } + + [Test] + public void InsertAndSelectBigClob() + { + //this is at least 5 MB + string largeString = new string('X', 1024 * 1024 * 5); + + //insert + dynamic item = new Entity("onmm3.bigclobtest"); + item.Text = largeString; + orm.Insert(item); + + //select + item = orm.Query("select * from onmm3.bigclobtest").SingleOrDefault(); + Assert.AreEqual(largeString, item.Text); + + //scalar + string largeStringFetched = orm.QueryScalar("select text from onmm3.bigclobtest"); + Assert.AreEqual(largeString, largeStringFetched); + } + + + [Test] + public void InsertBigClobWithNonQuery() + { + //this is at least 5 MB + string largeString = new string('X', 1024 * 1024 * 5); + + orm.NonQuery("insert into onmm3.bigclobtest (text) values (:0)", largeString); + + string largeStringFetched = orm.QueryScalar("select text from onmm3.bigclobtest"); + Assert.AreEqual(largeString, largeStringFetched); + } + + [Test] + public void SelectWithExternalConnection() + { + Console.WriteLine("InsertWithExternalConnectionAndSelectBigClob"); + + using (OracleConnection oracleConnection = new OracleConnection(orm.ConnectionString)) + { + oracleConnection.Open(); + using (var conncetion = orm.SetExternalConnection(oracleConnection)) + { + var r = orm.QueryScalar("select 1 from dual"); + Assert.AreEqual(1, r); + } + } + } + + [Test] + public void InsertWithExternalConnectionAndSelectBigClob() + { + Console.WriteLine("InsertWithExternalConnectionAndSelectBigClob"); + + using (OracleConnection oracleConnection = new OracleConnection(orm.ConnectionString)) + { + oracleConnection.Open(); + using (var conncetion = orm.SetExternalConnection(oracleConnection)) + { + //this is at least 5 MB + string largeString = new string('X', 1024 * 1024 * 1); + + //insert + dynamic item = new Entity("onmm3.bigclobtest"); + item.Text = largeString; + orm.Insert(item); + + //select + item = orm.Query("select * from onmm3.bigclobtest").SingleOrDefault(); + Assert.AreEqual(largeString, item.Text); + + //scalar + string largeStringFetched = orm.QueryScalar("select text from onmm3.bigclobtest"); + Assert.AreEqual(largeString, largeStringFetched); + } + } + } + + [Test] + public void DeleteWithCompositeKeyt() + { + dynamic item1 = new Entity("onmm3.item_composite_key", "id, type"); + item1.Id = 1; + item1.Type = 1; + orm.Insert(item1); + + dynamic item2 = new Entity("onmm3.item_composite_key", "id,type"); + item2.Id = 1; + item2.Type = 2; + orm.Insert(item2); + + orm.Delete(item1); + var list = orm.Query("select * from onmm3.item_composite_key"); + Assert.AreEqual(2, list.Single().Type); + + orm.Delete(item2); + Assert.AreEqual(0, orm.QueryScalar("select count(1) from onmm3.item_composite_key")); + } + + [Test] + public void OverflowDynamic() + { + Assert.Throws(() => orm.Query("select 1/3 decimal_value from dual").Single()); + Assert.Throws(() => orm.Query("select 999999999999999999999999999999 decimal_value from dual").Single()); + } + + [Test] + public void Overflow() + { + Assert.Throws(() => orm.Query("select 1/3 decimal_value from dual").Single()); + Assert.Throws(() => orm.Query("select 999999999999999999999999999999 decimal_value from dual").Single()); + } + + [Test] + public void LoadStaticShouldWarn() + { + DbMapper.PrintWarnings = true; + DbMapper.PrintSqls = true; + var item = orm.Query("select id, name, decimal_value, date_value from onmm3.item where id = :0", 1).SingleOrDefault(); + DbMapper.PrintWarnings = false; + DbMapper.PrintSqls = false; + } + + [Test] + public void CollectionShouldNotBeUsed() + { + ItemWithCollection item = new ItemWithCollection(); + item.Id = 3; + item.GroupsNotPresentInDb = new List() { 1 }; + orm.Insert(item, "onmm3.item"); + } + + [Test] + public void ConnectAsSys() + { + var orm = new DbMapper(); + orm.ConnectAsSys("tstdaily", "bi"); + orm.QueryScalar("select 1 from dual"); + } + + [TestCase("1\n2")] + [TestCase("1\r\n2")] + [TestCase("1\n\r2")] + [TestCase("1\r2")] + public void ClobTests(string testValue) + { + dynamic item = new Entity("onmm3.bigclobtest"); + item.Text = testValue; + orm.Insert(item); + + var fromDb = orm.QueryScalar("select text from onmm3.bigclobtest"); + Assert.AreEqual(testValue, fromDb); + } + + [Test] + public void NonQueryIgnoreErrorShouldWork() + { + orm.NonQueryIgnoreError("should not work"); + } + + [Test] + public void ToEntityShouldIgnoreListProperties() + { + var entity = new SomeClass() + .ToEntity(); + + var dic = entity.GetDictionary(); + + Assert.AreEqual(4, dic.Count); + Assert.IsTrue(dic.ContainsKey("Prop1")); + Assert.IsTrue(dic.ContainsKey("Prop2")); + Assert.IsTrue(dic.ContainsKey("Prop3")); + Assert.IsTrue(dic.ContainsKey("Prop4")); + + } + } + + class ProcParameters + { + public decimal Input { get; set; } + public decimal EchoOutput { get; set; } + public decimal CountOutput { get; set; } + public object FundsOutput { get; set; } + } + + public class Item + { + public int Id { get; set; } + public string Name { get; set; } + public decimal DecimalValue { get; set; } + public DateTime? DateValue { get; set; } + } + + public class ItemWithCollection + { + public int Id { get; set; } + public List GroupsNotPresentInDb { get; set; } + } + + public class ItemWrongDefinition + { + public int Id { get; set; } + public string Name { get; set; } + public decimal Decimalvalue { get; set; } + public DateTime? Datevalue { get; set; } + } + + class SomeClass + { + public string Prop1 { get; set; } + public decimal Prop2 { get; set; } + public DateTime Prop3 { get; set; } + public int? Prop4 { get; set; } + public List Col1 { get; set; } + public String[] Col2 { get; set; } + public Dictionary Col3 { get; set; } + } +} diff --git a/TestManagedCore/TestBase.cs b/TestManagedCore/TestBase.cs new file mode 100644 index 0000000..5cec4fc --- /dev/null +++ b/TestManagedCore/TestBase.cs @@ -0,0 +1,124 @@ +using System; +using NUnit.Framework; +using OdpNetMicroMapper; + +namespace TestManagedCore +{ + [TestFixture] + public class TestBase + { + static bool firstRun = true; + protected DbMapper orm = new DbMapper(); + protected DbMapper sysOrm = new DbMapper(); + + private void CreateUser() + { + if (!firstRun) + return; + + firstRun = false; + + sysOrm.NonQueryIgnoreError("drop user onmm3 cascade"); + sysOrm.NonQuery("create user onmm3 identified by onmm3"); + sysOrm.NonQuery("grant create session to onmm3"); + sysOrm.NonQuery("alter user onmm3 quota unlimited on users"); + Console.WriteLine("user onmm3 created"); + + var sql = "create table onmm3.bigclobtest (text clob)"; + sysOrm.NonQuery(sql); + + sql = "create table onmm3.rawtest (bytes raw(16))"; + sysOrm.NonQuery(sql); + + sql = "create table onmm3.item_with_long (text long)"; + sysOrm.NonQuery(sql); + + sql = @"create table onmm3.item_odd (id number(10) not null, yield_2date number)"; + sysOrm.NonQuery(sql); + + sql = @"create table onmm3.item_composite_key (id number(10) not null, type number(10) not null, text varchar2(100))"; + sysOrm.NonQuery(sql); + + sql = @"create table onmm3.item (id number(10) not null, name varchar2(100), decimal_value number, date_value timestamp default sysdate not null)"; + sysOrm.NonQuery(sql); + + sql = @"create sequence onmm3.seq_items start with 3"; + sysOrm.NonQuery(sql); + + sql = @"create or replace function onmm3.append1function (pString varchar2) return varchar2 + as + begin + return pString || '1'; + end;"; + //todo fix elsewhere? //http://boncode.blogspot.com/2009/03/oracle-pls-00103-encountered-symbol.html + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace function onmm3.plus1function (pNumber number) return integer + as + begin + return pNumber + 1; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace procedure onmm3.get_items_by_name(pName in varchar2, io_cursor out SYS_REFCURSOR) is + begin + open io_cursor for + select * from onmm3.item t where t.name = pName; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace procedure onmm3.rename_item(pId number, pName in varchar2) is + begin + update onmm3.item t set t.name = pName where t.id = pId; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + + sql = @"create or replace procedure onmm3.proc_with_many_out_parameters(pInput number, pEcho out number, pCount out number, io_cursor out SYS_REFCURSOR) is + begin + select pInput into pEcho from dual; + select count(1) into pCount from onmm3.fund; + open io_cursor for + select * from onmm3.fund; + end;"; + sql = sql.Replace(Environment.NewLine, "\n"); + sysOrm.NonQuery(sql); + } + + [TearDown] + public void DropSchema() + { + } + + [SetUp] + public void CreateSchema() + { + //throw new Exception("Please set 'data source' and 'password' in function CreateSchema()"); + + sysOrm.ConnectAsSys("INTSHARE", "bi"); + orm.ConnectionString = "data source=INTSHARE;user id=onmm3;password=onmm3;"; + + CreateUser(); + + sysOrm.NonQuery("delete from onmm3.item_composite_key"); + sysOrm.NonQuery("delete from onmm3.item"); + sysOrm.NonQuery("delete from onmm3.bigclobtest"); + sysOrm.NonQuery("delete from onmm3.item_with_long"); + sysOrm.NonQuery("delete from onmm3.item_odd"); + sysOrm.NonQuery("delete from onmm3.rawtest"); + + var sql = "insert into onmm3.item_odd (id, yield_2date) values (1, 99)"; + sysOrm.NonQuery(sql); + + sql = "insert into onmm3.item (id, name, decimal_value) values (1, 'First Item', 0.321)"; + sysOrm.NonQuery(sql); + + sql = "insert into onmm3.item (id, name, decimal_value) values (2, 'Second Item', 0.123)"; + sysOrm.NonQuery(sql); + + } + } +} diff --git a/TestManagedCore/TestManagedCore.csproj b/TestManagedCore/TestManagedCore.csproj new file mode 100644 index 0000000..d52e569 --- /dev/null +++ b/TestManagedCore/TestManagedCore.csproj @@ -0,0 +1,28 @@ + + + + netcoreapp2.0 + + + + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/TestManagedCore/sqlnet.ora b/TestManagedCore/sqlnet.ora new file mode 100644 index 0000000..858fe0d --- /dev/null +++ b/TestManagedCore/sqlnet.ora @@ -0,0 +1,5 @@ +# This file is actually generated by netca. But if customers choose to +# install "Software Only", this file wont exist and without the native +# authentication, they will not be able to connect to the database on NT. + +SQLNET.AUTHENTICATION_SERVICES = (NTS) diff --git a/TestManagedCore/tnsnames.ora b/TestManagedCore/tnsnames.ora new file mode 100644 index 0000000..a3d1a93 --- /dev/null +++ b/TestManagedCore/tnsnames.ora @@ -0,0 +1,149 @@ +# ____ ____ ___ ____ _ _ _ __ _____ ___ ___ _ _ ____ _ __ _ ___ _____ _ _ _____ _____ ____ +# | _ \ | _ \ / _ \ | _ \ | | | || |/ /|_ _||_ _|/ _ \ | \ | |/ ___| | |/ /| | |_ _|| ____|| \ | ||_ _|| ____|| _ \ +# | |_) || |_) || | | || | | || | | || ' / | | | || | | || \| |\___ \ | ' / | | | | | _| | \| | | | | _| | |_) | +# | __/ | _ < | |_| || |_| || |_| || . \ | | | || |_| || |\ | ___) | | . \ | |___ | | | |___ | |\ | | | | |___ | _ < +# |_| |_| \_\ \___/ |____/ \___/ |_|\_\ |_| |___|\___/ |_| \_||____/ |_|\_\|_____||___||_____||_| \_| |_| |_____||_| \_\ +# + + +AUDDB = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = AUDDB)) + ) + +CI = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA01.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = ORCL)) + ) + +INV = + (DESCRIPTION = + (ADDRESS = (PROTOCOL=TCP) (HOST=bidbs2003) (PORT=1521)) + (CONNECT_DATA = (SERVICE_NAME=invision)) + ) + +INVISION = + (DESCRIPTION = + (ADDRESS = (PROTOCOL=TCP) (HOST=bidbs2003) (PORT=1521)) + (CONNECT_DATA = (SERVICE_NAME=invision)) + ) + +PMFORUM = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA01.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = ORCL)) + ) + +ORA_ALIAS = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA01.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = ORCL)) + ) + +#Herunder er der kun testinstanser + +INV_TEST = (DESCRIPTION = + (ADDRESS_LIST = + (ADDRESS = (PROTOCOL = TCP)(HOST = bidbs2004.bi.local)(PORT = 1521)) + ) + (CONNECT_DATA = + (SERVICE_NAME = Invision) + ) + ) + +CIUDV = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = CIUDV)) + ) + +TEST = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = TEST)) + ) + +TSTDAILY = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = TSTDAILY)) + ) + +FPDTEST = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = FPDTEST)) + ) + +SUPDAILY = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = SUPDAILY)) + ) + +INTFID = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = INTFID)) + ) + +INTSHARE = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = INTSHARE)) + ) + +DEVSHARE = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = CIUDV)) + ) + +INTFMS = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = FMSREF)) + ) + +TSTWEEK = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = TEST)) + ) + +BIZTEST = + (DESCRIPTION = + (ADDRESS_LIST = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + ) + (CONNECT_DATA = + (SERVER = DEDICATED) + (SERVICE_NAME = BIZTEST)) + ) + +INVWEEK = + (DESCRIPTION= + (ADDRESS= (PROTOCOL=TCP) (HOST=bidbs2004) (PORT=1521)) + (CONNECT_DATA =(SERVICE_NAME=week)) + ) + +INVUDV = + (DESCRIPTION= + (ADDRESS= (PROTOCOL=TCP) (HOST=bidbs2004) (PORT=1521)) + (CONNECT_DATA =(SERVICE_NAME=udv)) + ) + +INVPRJKT = + (DESCRIPTION= + (ADDRESS = (PROTOCOL = TCP)(HOST=bidbs2004.bi.local)(PORT=1521)) + (CONNECT_DATA= + (SERVICE_NAME=INVPRJKT)) + ) + +TSTPRJKT = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = BICLUORA03.bi.local)(PORT = 1521)) + (CONNECT_DATA = (SID = TSTPRJKT)) + ) \ No newline at end of file diff --git a/Tests/App.config b/Tests/App.config index 05a3c21..a3548b0 100644 --- a/Tests/App.config +++ b/Tests/App.config @@ -1,11 +1,16 @@  + + + + + + + + + + + + - - - - - - \ No newline at end of file diff --git a/Tests/Properties/AssemblyInfo.cs b/Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index ad159e9..0000000 --- a/Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Test")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("Test")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("039db2c1-89f6-47d8-855d-a472a29ddf76")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tests/Test.cs b/Tests/Test.cs index acfdfb9..64f889b 100644 --- a/Tests/Test.cs +++ b/Tests/Test.cs @@ -30,7 +30,7 @@ public void RawTest() { var guid = new Guid(); orm.NonQuery("insert into onmm.rawtest (bytes) values (:0)", guid.ToByteArray()); - + var bytesLoaded = orm.QueryScalar("select bytes from onmm.rawtest where rownum = 1"); var guidLoaded = new Guid(bytesLoaded); Assert.AreEqual(guid, guidLoaded); @@ -48,7 +48,7 @@ public void InsertDynamicTest(string type) item.Id = 3; item.Name = "Third Item"; item.DateValue = DateTime.Today; - if (type=="double") item.DecimalValue = 3.1415d; + if (type == "double") item.DecimalValue = 3.1415d; if (type == "float") item.DecimalValue = 3.1415f; if (type == "decimal") item.DecimalValue = 3.1415m; @@ -80,7 +80,7 @@ public void UpdateDynamicWithNull() public void InsertWithLongColumnMax4000chars() { dynamic item = new Entity("onmm.item_with_long"); - item.Text = new string('X', 1000 * 4 ); //max 4k when inserting! + item.Text = new string('X', 1000 * 4); //max 4k when inserting! orm.Insert(item); var items = orm.Query("select * from onmm.item_with_long"); @@ -92,7 +92,7 @@ public void DeleteWithWhereClause() { dynamic item = new Entity("onmm.item"); Assert.AreEqual(2, orm.QueryScalar("select count(1) from onmm.item")); - + orm.Delete(item, "where id = :0", 1); Assert.AreEqual(1, orm.QueryScalar("select count(1) from onmm.item")); @@ -216,8 +216,8 @@ public void ColumnWithUnderScoreBeforeDigit() public void QueryDynamicToString() { var item = orm.Query("select * from onmm.item where id = 1").Single(); - Assert.That(item.ToString(), Is.StringContaining("Id = 1")); - Assert.That(item.ToString(), Is.StringContaining("Name = First Item")); + Assert.That(item.ToString(), Contains.Substring("Id = 1")); + Assert.That(item.ToString(), Contains.Substring("Name = First Item")); } [Test] @@ -280,7 +280,7 @@ public void ExecuteFunctionWithInt() [Test] public void ExecuteFunctionWithString() - { + { var result = orm.ExecuteFunction("onmm.append1function", "100"); Assert.AreEqual("1001", result); } @@ -373,7 +373,7 @@ public void InsertWithExplicitConnectionAndTransaction() public void InsertAndSelectBigClob() { //this is at least 5 MB - string largeString = new string ('X', 1024*1024*5); + string largeString = new string('X', 1024 * 1024 * 5); //insert dynamic item = new Entity("onmm.bigclobtest"); @@ -497,7 +497,7 @@ public void CollectionShouldNotBeUsed() { ItemWithCollection item = new ItemWithCollection(); item.Id = 3; - item.GroupsNotPresentInDb = new List() { 1 }; + item.GroupsNotPresentInDb = new List() { 1 }; orm.Insert(item, "onmm.item"); } diff --git a/Tests/TestBase.cs b/Tests/TestBase.cs index 3ffe646..66ea049 100644 --- a/Tests/TestBase.cs +++ b/Tests/TestBase.cs @@ -96,10 +96,10 @@ public void DropSchema() [SetUp] public void CreateSchema() { - throw new Exception("Please set 'data source' and 'password' in function CreateSchema()"); +// throw new Exception("Please set 'data source' and 'password' in function CreateSchema()"); - sysOrm.ConnectAsSys("tns", "password"); - orm.ConnectionString = "data source=tns;user id=onmm;password=onmm;"; + sysOrm.ConnectAsSys("intshare", "bi"); + orm.ConnectionString = "data source=intshare;user id=onmm;password=onmm;"; CreateUser(); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 82910ec..fe8c67d 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,84 +1,25 @@ - - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {CC7CDBB4-E507-4558-A7DE-9800D19624D7} - Library - Properties - Test - Test - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + net461 + - - ..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll - - - ..\packages\NUnit.2.5.10.11092\lib\nunit.mocks.dll - + + + C:\Oracle\Product\11.2.0.3.0_32\odp.net\bin\2.x\Oracle.DataAccess.dll False - False - - ..\packages\NUnit.2.5.10.11092\lib\pnunit.framework.dll - - - - - - - - - - - - - - - + - - Designer - - - Designer - + + - - {A18AC73A-2B4B-4D66-BF15-1094CBEDCC1F} - OdpNetMicroMapper - + - - - \ No newline at end of file + + + diff --git a/Tests/packages.config b/Tests/packages.config deleted file mode 100644 index 0c82178..0000000 --- a/Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/changeLog.txt b/changeLog.txt new file mode 100644 index 0000000..e69de29 diff --git a/packages/repositories.config b/packages/repositories.config deleted file mode 100644 index fa38fcf..0000000 --- a/packages/repositories.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file