From 31dd69dfc55c4a72c8846d46e391b7fc9363331a Mon Sep 17 00:00:00 2001 From: "grzegorz.russek" Date: Fri, 15 May 2015 23:11:59 +0000 Subject: [PATCH] --- AmalgamationTool/DynamORM.Amalgamation.cs | 320 +++++++++++++++++- DynamORM.Tests/Helpers/AttachToDebugger.cs | 2 +- .../Helpers/Dynamic/DynamicParserTests.cs | 2 +- DynamORM.Tests/Helpers/PoolingTests.cs | 2 +- DynamORM.Tests/Helpers/Users.cs | 2 +- DynamORM.Tests/Helpers/UsersBareBoneClass.cs | 2 +- .../Modify/DynamicModificationTests.cs | 2 +- .../DynamicNoSchemaModificationTests.cs | 2 +- .../DynamicTypeSchemaModificationTests.cs | 2 +- DynamORM.Tests/Modify/ParserTests.cs | 2 +- DynamORM.Tests/Properties/AssemblyInfo.cs | 2 +- DynamORM.Tests/Select/DynamicAccessTests.cs | 2 +- .../Select/DynamicNoSchemaAccessTests.cs | 2 +- .../Select/DynamicTypeSchemaAccessTests.cs | 2 +- DynamORM.Tests/Select/LegacyParserTests.cs | 2 +- DynamORM.Tests/Select/ParserTests.cs | 2 +- .../Select/RenamedTypedAccessTests.cs | 2 +- DynamORM.Tests/Select/TypedAccessTests.cs | 2 +- DynamORM.Tests/TestsBase.cs | 2 +- .../DynamicModifyBuilderExtensions.cs | 2 +- .../Extensions/DynamicWhereQueryExtensions.cs | 2 +- .../Builders/IDynamicDeleteQueryBuilder.cs | 2 +- .../Builders/IDynamicInsertQueryBuilder.cs | 2 +- DynamORM/Builders/IDynamicQueryBuilder.cs | 2 +- .../Builders/IDynamicSelectQueryBuilder.cs | 2 +- .../Builders/IDynamicUpdateQueryBuilder.cs | 2 +- DynamORM/Builders/IParameter.cs | 2 +- DynamORM/Builders/ITableInfo.cs | 2 +- .../DynamicDeleteQueryBuilder.cs | 2 +- .../DynamicInsertQueryBuilder.cs | 2 +- .../Implementation/DynamicModifyBuilder.cs | 2 +- .../Implementation/DynamicQueryBuilder.cs | 2 +- .../DynamicSelectQueryBuilder.cs | 2 +- .../DynamicUpdateQueryBuilder.cs | 2 +- DynamORM/DynamORM.csproj | 2 + DynamORM/DynamicColumn.cs | 2 +- DynamORM/DynamicCommand.cs | 2 +- DynamORM/DynamicConnection.cs | 2 +- DynamORM/DynamicDatabase.cs | 22 +- DynamORM/DynamicDatabaseOptions.cs | 2 +- DynamORM/DynamicExpando.cs | 2 +- DynamORM/DynamicExtensions.cs | 17 +- DynamORM/DynamicProcedureInvoker.cs | 236 +++++++++++++ DynamORM/DynamicQueryException.cs | 2 +- DynamORM/DynamicSchemaColumn.cs | 2 +- DynamORM/DynamicTable.cs | 2 +- DynamORM/DynamicTransaction.cs | 2 +- DynamORM/Helpers/CollectionComparer.cs | 2 +- DynamORM/Helpers/Dynamics/DynamicParser.cs | 2 +- DynamORM/Helpers/Dynamics/DynamicProxy.cs | 2 +- DynamORM/Helpers/FrameworkTools.cs | 2 +- DynamORM/Helpers/IExtendedDisposable.cs | 2 +- DynamORM/Helpers/IFinalizerDisposable.cs | 2 +- DynamORM/Helpers/StringExtensions.cs | 2 +- DynamORM/Helpers/UnclassifiedExtensions.cs | 2 +- DynamORM/Mapper/ColumnAttribute.cs | 2 +- DynamORM/Mapper/DynamicCast.cs | 120 +++++++ DynamORM/Mapper/DynamicMapperCache.cs | 2 +- DynamORM/Mapper/DynamicPropertyInvoker.cs | 2 +- DynamORM/Mapper/DynamicTypeMap.cs | 2 +- DynamORM/Mapper/IgnoreAttribute.cs | 2 +- DynamORM/Mapper/TableAttribute.cs | 2 +- DynamORM/Properties/AssemblyInfo.cs | 2 +- Tester/Program.cs | 226 ++----------- 64 files changed, 794 insertions(+), 263 deletions(-) create mode 100644 DynamORM/DynamicProcedureInvoker.cs create mode 100644 DynamORM/Mapper/DynamicCast.cs diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs index 1b53e1b..8045f48 100644 --- a/AmalgamationTool/DynamORM.Amalgamation.cs +++ b/AmalgamationTool/DynamORM.Amalgamation.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Data; @@ -935,6 +936,7 @@ namespace DynamORM #region Internal fields and properties private DbProviderFactory _provider; + private DynamicProcedureInvoker _proc; private string _connectionString; private bool _singleConnection; private bool _singleTransaction; @@ -1006,6 +1008,23 @@ namespace DynamORM /// Gets the database provider. public DbProviderFactory Provider { get { return _provider; } } + /// Gets the procedures invoker. + public dynamic Procedures + { + get + { + if (_proc == null) + { + if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures) + throw new InvalidOperationException("Database connection desn't support stored procedures."); + + _proc = new DynamicProcedureInvoker(this); + } + + return _proc; + } + } + /// Gets or sets a value indicating whether /// dump commands to console or not. public bool DumpCommands { get; set; } @@ -2636,6 +2655,8 @@ namespace DynamORM } ClearSchema(); + if (_proc != null) + _proc.Dispose(); IsDisposed = true; } @@ -3007,7 +3028,14 @@ namespace DynamORM { if (args != null && args.Count() > 0) foreach (object item in args) - cmd.AddParameter(database, item); + { + if (item is DynamicExpando) + cmd.AddParameters(database, (DynamicExpando)item); + else if (item is ExpandoObject) + cmd.AddParameters(database, (ExpandoObject)item); + else + cmd.AddParameter(database, item); + } return cmd; } @@ -4210,6 +4238,12 @@ namespace DynamORM return TypeMap.TryGetNullable(r.GetFieldType(i)) ?? DbType.String; } + internal static IEnumerable EnumerateReader(this IDataReader r) + { + while (r.Read()) + yield return r.RowToDynamic(); + } + #endregion IDataReader extensions #region Mapper extensions @@ -4383,6 +4417,203 @@ namespace DynamORM #endregion Coalesce - besicaly not an extensions } + /// Dynamic procedure invoker. + /// Unfortunately I can use out and ref to + /// return parameters, . + /// But see example for workaround. If there aren't any return parameters execution will return scalar value. + /// Scalar result is not converted to provided generic type (if any). For output results there is possibility to map to provided class. + /// You still can use out, return and both way parameters by providing variable prefix: + /// dynamic res = db.Procedures.sp_Test_Scalar_In_Out(inp: Guid.NewGuid(), out_outp: Guid.Empty); + /// Console.Out.WriteLine(res.outp); + /// Prefixes: out_, ret_, both_. Result will contain field without prefix. + /// Here is an example with result class: + /// public class ProcResult { [Column("outp")] public Guid Output { get; set; } } + /// ProcResult res4 = db.Procedures.sp_Test_Scalar_In_Out<ProcResult>(inp: Guid.NewGuid(), out_outp: Guid.Empty) as ProcResult; + /// As you can se, you can use mapper to do job for you. + public class DynamicProcedureInvoker : DynamicObject, IDisposable + { + private DynamicDatabase _db; + + internal DynamicProcedureInvoker(DynamicDatabase db) + { + _db = db; + } + + /// This is where the magic begins. + /// Binder to invoke. + /// Binder arguments. + /// Binder invoke result. + /// Returns true if invoke was performed. + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) + { + // parse the method + CallInfo info = binder.CallInfo; + + // Get generic types + IList types = binder.GetGenericTypeArguments(); + + Dictionary retParams = null; + + using (IDbConnection con = _db.Open()) + using (IDbCommand cmd = con.CreateCommand()) + { + cmd.SetCommand(CommandType.StoredProcedure, binder.Name); + + #region Prepare arguments + + int alen = args.Length; + if (alen > 0) + { + for (int i = 0; i < alen; i++) + { + object arg = args[i]; + + if (arg is DynamicExpando) + cmd.AddParameters(_db, (DynamicExpando)arg); + else if (arg is ExpandoObject) + cmd.AddParameters(_db, (ExpandoObject)arg); + else + { + if (info.ArgumentNames.Count > i && !string.IsNullOrEmpty(info.ArgumentNames[i])) + { + bool isOut = info.ArgumentNames[i].StartsWith("out_"); + bool isRet = info.ArgumentNames[i].StartsWith("ret_"); + bool isBoth = info.ArgumentNames[i].StartsWith("both_"); + string paramName = isOut || isRet ? + info.ArgumentNames[i].Substring(4) : + isBoth ? info.ArgumentNames[i].Substring(5) : + info.ArgumentNames[i]; + + if (isOut || isBoth || isRet) + { + if (retParams == null) + retParams = new Dictionary(); + retParams.Add(paramName, cmd.Parameters.Count); + } + + cmd.AddParameter( + _db.GetParameterName(paramName), + isOut ? ParameterDirection.Output : + isRet ? ParameterDirection.ReturnValue : + isBoth ? ParameterDirection.InputOutput : ParameterDirection.Input, + arg == null ? DbType.String : arg.GetType().ToDbType(), 0, isOut ? DBNull.Value : arg); + } + else + cmd.AddParameter(_db, arg); + } + } + } + + #endregion Prepare arguments + + #region Get main result + + object mainResult = null; + + if (types.Count > 0) + { + mainResult = types[0].GetDefaultValue(); + + if (types[0] == typeof(IDataReader)) + mainResult = cmd.ExecuteReader(); + else if (types[0].IsGenericEnumerable()) + { + Type argType = types[0].GetGenericArguments().First(); + if (argType == typeof(object)) + using (IDataReader rdr = cmd.ExecuteReader()) + mainResult = rdr.EnumerateReader().ToList(); + else if (argType.IsValueType) + { + Type listType = typeof(List<>).MakeGenericType(new Type[] { argType }); + IList listInstance = (IList)Activator.CreateInstance(listType); + + object defVal = listType.GetDefaultValue(); + + using (IDataReader rdr = cmd.ExecuteReader()) + while (rdr.Read()) + listInstance.Add(rdr[0] == DBNull.Value ? defVal : argType.CastObject(rdr[0])); + + mainResult = listInstance; + } + else + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(argType); + if (mapper == null) + throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", argType.ToString())); + + using (IDataReader rdr = cmd.ExecuteReader()) + mainResult = rdr.EnumerateReader().MapEnumerable(argType).ToList(); + } + } + else if (types[0].IsValueType) + { + mainResult = cmd.ExecuteScalar(); + if (mainResult != DBNull.Value) + mainResult = types[0].CastObject(mainResult); + } + else + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(types[0]); + if (mapper == null) + throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", types[0].ToString())); + + using (IDataReader rdr = cmd.ExecuteReader()) + if (rdr.Read()) + mainResult = (rdr.ToDynamic() as object).Map(types[0]); + else + mainResult = null; + } + } + else + mainResult = cmd.ExecuteNonQuery(); + + #endregion Get main result + + #region Handle out params + + if (retParams != null) + { + Dictionary res = new Dictionary(); + + if (mainResult != null) + { + if (mainResult == DBNull.Value) + res.Add(binder.Name, null); + else + res.Add(binder.Name, mainResult); + } + + foreach (KeyValuePair pos in retParams) + res.Add(pos.Key, ((IDbDataParameter)cmd.Parameters[pos.Value]).Value); + + if (types.Count > 1) + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(types[1]); + + if (mapper != null) + result = mapper.Create(res.ToDynamic()); + else + result = res.ToDynamic(); + } + else + result = res.ToDynamic(); + } + else + result = mainResult; + + #endregion Handle out params + } + + return true; + } + + /// Performs application-defined tasks associated with + /// freeing, releasing, or resetting unmanaged resources. + public void Dispose() + { + } + } + /// Dynamic query exception. [Serializable] public class DynamicQueryException : Exception, ISerializable @@ -11307,6 +11538,91 @@ namespace DynamORM #endregion Constructors } + /// Type cast helper. + public static class DynamicCast + { + /// Gets the default value. + /// The type. + /// Default instance. + public static object GetDefaultValue(this Type type) + { + return type.IsValueType ? TypeDefaults.GetOrAdd(type, t => Activator.CreateInstance(t)) : null; + } + + /// Casts the object to this type. + /// The type to which cast value. + /// The value to cast. + /// Value casted to new type. + public static object CastObject(this Type type, object val) + { + return GetConverter(type, val)(val); + } + + private static readonly ConcurrentDictionary TypeDefaults = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary> TypeAsCasts = new ConcurrentDictionary>(); + private static readonly ConcurrentDictionary> TypeConvert = new ConcurrentDictionary>(); + private static readonly ParameterExpression ConvParameter = Expression.Parameter(typeof(object), "val"); + + [MethodImpl(MethodImplOptions.Synchronized)] + private static Func GetConverter(Type targetType, object val) + { + Func fn; + + if (!targetType.IsValueType && !val.GetType().IsValueType) + { + if (!TypeAsCasts.TryGetValue(targetType, out fn)) + { + UnaryExpression instanceCast = Expression.TypeAs(ConvParameter, targetType); + + fn = Expression.Lambda>(Expression.TypeAs(instanceCast, typeof(object)), ConvParameter).Compile(); + TypeAsCasts.AddOrUpdate(targetType, fn, (t, f) => fn); + } + } + else + { + var fromType = val != null ? val.GetType() : typeof(object); + var key = new PairOfTypes(fromType, targetType); + if (TypeConvert.TryGetValue(key, out fn)) + return fn; + + fn = (Func)Expression.Lambda(Expression.Convert(Expression.Convert(Expression.Convert(ConvParameter, fromType), targetType), typeof(object)), ConvParameter).Compile(); + TypeConvert.AddOrUpdate(key, fn, (t, f) => fn); + } + + return fn; + } + + private class PairOfTypes + { + private readonly Type _first; + private readonly Type _second; + + public PairOfTypes(Type first, Type second) + { + this._first = first; + this._second = second; + } + + public override int GetHashCode() + { + return (31 * _first.GetHashCode()) + _second.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj == this) + return true; + + var other = obj as PairOfTypes; + if (other == null) + return false; + + return _first.Equals(other._first) + && _second.Equals(other._second); + } + } + } + /// Class with mapper cache. public static class DynamicMapperCache { diff --git a/DynamORM.Tests/Helpers/AttachToDebugger.cs b/DynamORM.Tests/Helpers/AttachToDebugger.cs index d920611..72992e1 100644 --- a/DynamORM.Tests/Helpers/AttachToDebugger.cs +++ b/DynamORM.Tests/Helpers/AttachToDebugger.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Helpers/Dynamic/DynamicParserTests.cs b/DynamORM.Tests/Helpers/Dynamic/DynamicParserTests.cs index 1c7d1c7..5d07f1f 100644 --- a/DynamORM.Tests/Helpers/Dynamic/DynamicParserTests.cs +++ b/DynamORM.Tests/Helpers/Dynamic/DynamicParserTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Helpers/PoolingTests.cs b/DynamORM.Tests/Helpers/PoolingTests.cs index 1ce1ba2..cd8409e 100644 --- a/DynamORM.Tests/Helpers/PoolingTests.cs +++ b/DynamORM.Tests/Helpers/PoolingTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Helpers/Users.cs b/DynamORM.Tests/Helpers/Users.cs index c29917c..f7b4e4d 100644 --- a/DynamORM.Tests/Helpers/Users.cs +++ b/DynamORM.Tests/Helpers/Users.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Helpers/UsersBareBoneClass.cs b/DynamORM.Tests/Helpers/UsersBareBoneClass.cs index 82ee275..3b72195 100644 --- a/DynamORM.Tests/Helpers/UsersBareBoneClass.cs +++ b/DynamORM.Tests/Helpers/UsersBareBoneClass.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Modify/DynamicModificationTests.cs b/DynamORM.Tests/Modify/DynamicModificationTests.cs index b5ecbd2..f25b96e 100644 --- a/DynamORM.Tests/Modify/DynamicModificationTests.cs +++ b/DynamORM.Tests/Modify/DynamicModificationTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Modify/DynamicNoSchemaModificationTests.cs b/DynamORM.Tests/Modify/DynamicNoSchemaModificationTests.cs index 05a13df..7591500 100644 --- a/DynamORM.Tests/Modify/DynamicNoSchemaModificationTests.cs +++ b/DynamORM.Tests/Modify/DynamicNoSchemaModificationTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Modify/DynamicTypeSchemaModificationTests.cs b/DynamORM.Tests/Modify/DynamicTypeSchemaModificationTests.cs index f29d559..a0e360a 100644 --- a/DynamORM.Tests/Modify/DynamicTypeSchemaModificationTests.cs +++ b/DynamORM.Tests/Modify/DynamicTypeSchemaModificationTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Modify/ParserTests.cs b/DynamORM.Tests/Modify/ParserTests.cs index 2c56c41..de54826 100644 --- a/DynamORM.Tests/Modify/ParserTests.cs +++ b/DynamORM.Tests/Modify/ParserTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Properties/AssemblyInfo.cs b/DynamORM.Tests/Properties/AssemblyInfo.cs index d285638..ce5b32b 100644 --- a/DynamORM.Tests/Properties/AssemblyInfo.cs +++ b/DynamORM.Tests/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/DynamicAccessTests.cs b/DynamORM.Tests/Select/DynamicAccessTests.cs index 9a9e18c..89734a4 100644 --- a/DynamORM.Tests/Select/DynamicAccessTests.cs +++ b/DynamORM.Tests/Select/DynamicAccessTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/DynamicNoSchemaAccessTests.cs b/DynamORM.Tests/Select/DynamicNoSchemaAccessTests.cs index 56d9090..3c551a0 100644 --- a/DynamORM.Tests/Select/DynamicNoSchemaAccessTests.cs +++ b/DynamORM.Tests/Select/DynamicNoSchemaAccessTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/DynamicTypeSchemaAccessTests.cs b/DynamORM.Tests/Select/DynamicTypeSchemaAccessTests.cs index 73a2c47..3e2e505 100644 --- a/DynamORM.Tests/Select/DynamicTypeSchemaAccessTests.cs +++ b/DynamORM.Tests/Select/DynamicTypeSchemaAccessTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/LegacyParserTests.cs b/DynamORM.Tests/Select/LegacyParserTests.cs index cb1f38c..fb34422 100644 --- a/DynamORM.Tests/Select/LegacyParserTests.cs +++ b/DynamORM.Tests/Select/LegacyParserTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/ParserTests.cs b/DynamORM.Tests/Select/ParserTests.cs index 9f59eac..567615b 100644 --- a/DynamORM.Tests/Select/ParserTests.cs +++ b/DynamORM.Tests/Select/ParserTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/RenamedTypedAccessTests.cs b/DynamORM.Tests/Select/RenamedTypedAccessTests.cs index 9191154..3ea71f4 100644 --- a/DynamORM.Tests/Select/RenamedTypedAccessTests.cs +++ b/DynamORM.Tests/Select/RenamedTypedAccessTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/Select/TypedAccessTests.cs b/DynamORM.Tests/Select/TypedAccessTests.cs index c054d55..1c8e0ed 100644 --- a/DynamORM.Tests/Select/TypedAccessTests.cs +++ b/DynamORM.Tests/Select/TypedAccessTests.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM.Tests/TestsBase.cs b/DynamORM.Tests/TestsBase.cs index e08719a..d5a0551 100644 --- a/DynamORM.Tests/TestsBase.cs +++ b/DynamORM.Tests/TestsBase.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/Extensions/DynamicModifyBuilderExtensions.cs b/DynamORM/Builders/Extensions/DynamicModifyBuilderExtensions.cs index 3a4e306..4e99d7c 100644 --- a/DynamORM/Builders/Extensions/DynamicModifyBuilderExtensions.cs +++ b/DynamORM/Builders/Extensions/DynamicModifyBuilderExtensions.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/Builders/Extensions/DynamicWhereQueryExtensions.cs b/DynamORM/Builders/Extensions/DynamicWhereQueryExtensions.cs index 191610c..5dbbed9 100644 --- a/DynamORM/Builders/Extensions/DynamicWhereQueryExtensions.cs +++ b/DynamORM/Builders/Extensions/DynamicWhereQueryExtensions.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/Builders/IDynamicDeleteQueryBuilder.cs b/DynamORM/Builders/IDynamicDeleteQueryBuilder.cs index f9dcfa0..17629aa 100644 --- a/DynamORM/Builders/IDynamicDeleteQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicDeleteQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/IDynamicInsertQueryBuilder.cs b/DynamORM/Builders/IDynamicInsertQueryBuilder.cs index 0bf7c07..e7e2cde 100644 --- a/DynamORM/Builders/IDynamicInsertQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicInsertQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/IDynamicQueryBuilder.cs b/DynamORM/Builders/IDynamicQueryBuilder.cs index bcebf64..62b2554 100644 --- a/DynamORM/Builders/IDynamicQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/IDynamicSelectQueryBuilder.cs b/DynamORM/Builders/IDynamicSelectQueryBuilder.cs index 9b3fd29..9e97307 100644 --- a/DynamORM/Builders/IDynamicSelectQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicSelectQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/IDynamicUpdateQueryBuilder.cs b/DynamORM/Builders/IDynamicUpdateQueryBuilder.cs index c317454..5f83381 100644 --- a/DynamORM/Builders/IDynamicUpdateQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicUpdateQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/IParameter.cs b/DynamORM/Builders/IParameter.cs index 629da90..999e3f9 100644 --- a/DynamORM/Builders/IParameter.cs +++ b/DynamORM/Builders/IParameter.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/ITableInfo.cs b/DynamORM/Builders/ITableInfo.cs index e1b5608..4059796 100644 --- a/DynamORM/Builders/ITableInfo.cs +++ b/DynamORM/Builders/ITableInfo.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/Implementation/DynamicDeleteQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicDeleteQueryBuilder.cs index aff92be..25ebdc0 100644 --- a/DynamORM/Builders/Implementation/DynamicDeleteQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicDeleteQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs index 2210c59..3bb8223 100644 --- a/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/Builders/Implementation/DynamicModifyBuilder.cs b/DynamORM/Builders/Implementation/DynamicModifyBuilder.cs index e3db206..2bf7a38 100644 --- a/DynamORM/Builders/Implementation/DynamicModifyBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicModifyBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Builders/Implementation/DynamicQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicQueryBuilder.cs index e80fb20..4e3c569 100644 --- a/DynamORM/Builders/Implementation/DynamicQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs index e8dfc76..398cb2e 100644 --- a/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs index aceedec..a6b049c 100644 --- a/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Some of methods in this code file is based on Kerosene ORM solution diff --git a/DynamORM/DynamORM.csproj b/DynamORM/DynamORM.csproj index 865a481..c7c72bd 100644 --- a/DynamORM/DynamORM.csproj +++ b/DynamORM/DynamORM.csproj @@ -85,6 +85,7 @@ + @@ -102,6 +103,7 @@ + diff --git a/DynamORM/DynamicColumn.cs b/DynamORM/DynamicColumn.cs index 61d22bd..b99e6a8 100644 --- a/DynamORM/DynamicColumn.cs +++ b/DynamORM/DynamicColumn.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicCommand.cs b/DynamORM/DynamicCommand.cs index c2a35da..08816ee 100644 --- a/DynamORM/DynamicCommand.cs +++ b/DynamORM/DynamicCommand.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicConnection.cs b/DynamORM/DynamicConnection.cs index bd01537..45cac06 100644 --- a/DynamORM/DynamicConnection.cs +++ b/DynamORM/DynamicConnection.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicDatabase.cs b/DynamORM/DynamicDatabase.cs index 1fc7061..7da2e19 100644 --- a/DynamORM/DynamicDatabase.cs +++ b/DynamORM/DynamicDatabase.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,7 @@ namespace DynamORM #region Internal fields and properties private DbProviderFactory _provider; + private DynamicProcedureInvoker _proc; private string _connectionString; private bool _singleConnection; private bool _singleTransaction; @@ -118,6 +119,23 @@ namespace DynamORM /// Gets the database provider. public DbProviderFactory Provider { get { return _provider; } } + /// Gets the procedures invoker. + public dynamic Procedures + { + get + { + if (_proc == null) + { + if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures) + throw new InvalidOperationException("Database connection desn't support stored procedures."); + + _proc = new DynamicProcedureInvoker(this); + } + + return _proc; + } + } + /// Gets or sets a value indicating whether /// dump commands to console or not. public bool DumpCommands { get; set; } @@ -1748,6 +1766,8 @@ namespace DynamORM } ClearSchema(); + if (_proc != null) + _proc.Dispose(); IsDisposed = true; } diff --git a/DynamORM/DynamicDatabaseOptions.cs b/DynamORM/DynamicDatabaseOptions.cs index 3410c45..0b61a22 100644 --- a/DynamORM/DynamicDatabaseOptions.cs +++ b/DynamORM/DynamicDatabaseOptions.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicExpando.cs b/DynamORM/DynamicExpando.cs index 99b069c..7cca1bb 100644 --- a/DynamORM/DynamicExpando.cs +++ b/DynamORM/DynamicExpando.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicExtensions.cs b/DynamORM/DynamicExtensions.cs index ffe6d78..8d020e1 100644 --- a/DynamORM/DynamicExtensions.cs +++ b/DynamORM/DynamicExtensions.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -210,7 +210,14 @@ namespace DynamORM { if (args != null && args.Count() > 0) foreach (object item in args) - cmd.AddParameter(database, item); + { + if (item is DynamicExpando) + cmd.AddParameters(database, (DynamicExpando)item); + else if (item is ExpandoObject) + cmd.AddParameters(database, (ExpandoObject)item); + else + cmd.AddParameter(database, item); + } return cmd; } @@ -1413,6 +1420,12 @@ namespace DynamORM return TypeMap.TryGetNullable(r.GetFieldType(i)) ?? DbType.String; } + internal static IEnumerable EnumerateReader(this IDataReader r) + { + while (r.Read()) + yield return r.RowToDynamic(); + } + #endregion IDataReader extensions #region Mapper extensions diff --git a/DynamORM/DynamicProcedureInvoker.cs b/DynamORM/DynamicProcedureInvoker.cs new file mode 100644 index 0000000..d1bfca8 --- /dev/null +++ b/DynamORM/DynamicProcedureInvoker.cs @@ -0,0 +1,236 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using DynamORM.Helpers; +using DynamORM.Mapper; + +namespace DynamORM +{ + /// Dynamic procedure invoker. + /// Unfortunately I can use out and ref to + /// return parameters, . + /// But see example for workaround. If there aren't any return parameters execution will return scalar value. + /// Scalar result is not converted to provided generic type (if any). For output results there is possibility to map to provided class. + /// You still can use out, return and both way parameters by providing variable prefix: + /// dynamic res = db.Procedures.sp_Test_Scalar_In_Out(inp: Guid.NewGuid(), out_outp: Guid.Empty); + /// Console.Out.WriteLine(res.outp); + /// Prefixes: out_, ret_, both_. Result will contain field without prefix. + /// Here is an example with result class: + /// public class ProcResult { [Column("outp")] public Guid Output { get; set; } } + /// ProcResult res4 = db.Procedures.sp_Test_Scalar_In_Out<ProcResult>(inp: Guid.NewGuid(), out_outp: Guid.Empty) as ProcResult; + /// As you can se, you can use mapper to do job for you. + public class DynamicProcedureInvoker : DynamicObject, IDisposable + { + private DynamicDatabase _db; + + internal DynamicProcedureInvoker(DynamicDatabase db) + { + _db = db; + } + + /// This is where the magic begins. + /// Binder to invoke. + /// Binder arguments. + /// Binder invoke result. + /// Returns true if invoke was performed. + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) + { + // parse the method + CallInfo info = binder.CallInfo; + + // Get generic types + IList types = binder.GetGenericTypeArguments(); + + Dictionary retParams = null; + + using (IDbConnection con = _db.Open()) + using (IDbCommand cmd = con.CreateCommand()) + { + cmd.SetCommand(CommandType.StoredProcedure, binder.Name); + + #region Prepare arguments + + int alen = args.Length; + if (alen > 0) + { + for (int i = 0; i < alen; i++) + { + object arg = args[i]; + + if (arg is DynamicExpando) + cmd.AddParameters(_db, (DynamicExpando)arg); + else if (arg is ExpandoObject) + cmd.AddParameters(_db, (ExpandoObject)arg); + else + { + if (info.ArgumentNames.Count > i && !string.IsNullOrEmpty(info.ArgumentNames[i])) + { + bool isOut = info.ArgumentNames[i].StartsWith("out_"); + bool isRet = info.ArgumentNames[i].StartsWith("ret_"); + bool isBoth = info.ArgumentNames[i].StartsWith("both_"); + string paramName = isOut || isRet ? + info.ArgumentNames[i].Substring(4) : + isBoth ? info.ArgumentNames[i].Substring(5) : + info.ArgumentNames[i]; + + if (isOut || isBoth || isRet) + { + if (retParams == null) + retParams = new Dictionary(); + retParams.Add(paramName, cmd.Parameters.Count); + } + + cmd.AddParameter( + _db.GetParameterName(paramName), + isOut ? ParameterDirection.Output : + isRet ? ParameterDirection.ReturnValue : + isBoth ? ParameterDirection.InputOutput : ParameterDirection.Input, + arg == null ? DbType.String : arg.GetType().ToDbType(), 0, isOut ? DBNull.Value : arg); + } + else + cmd.AddParameter(_db, arg); + } + } + } + + #endregion Prepare arguments + + #region Get main result + + object mainResult = null; + + if (types.Count > 0) + { + mainResult = types[0].GetDefaultValue(); + + if (types[0] == typeof(IDataReader)) + mainResult = cmd.ExecuteReader(); + else if (types[0].IsGenericEnumerable()) + { + Type argType = types[0].GetGenericArguments().First(); + if (argType == typeof(object)) + using (IDataReader rdr = cmd.ExecuteReader()) + mainResult = rdr.EnumerateReader().ToList(); + else if (argType.IsValueType) + { + Type listType = typeof(List<>).MakeGenericType(new Type[] { argType }); + IList listInstance = (IList)Activator.CreateInstance(listType); + + object defVal = listType.GetDefaultValue(); + + using (IDataReader rdr = cmd.ExecuteReader()) + while (rdr.Read()) + listInstance.Add(rdr[0] == DBNull.Value ? defVal : argType.CastObject(rdr[0])); + + mainResult = listInstance; + } + else + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(argType); + if (mapper == null) + throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", argType.ToString())); + + using (IDataReader rdr = cmd.ExecuteReader()) + mainResult = rdr.EnumerateReader().MapEnumerable(argType).ToList(); + } + } + else if (types[0].IsValueType) + { + mainResult = cmd.ExecuteScalar(); + if (mainResult != DBNull.Value) + mainResult = types[0].CastObject(mainResult); + } + else + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(types[0]); + if (mapper == null) + throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", types[0].ToString())); + + using (IDataReader rdr = cmd.ExecuteReader()) + if (rdr.Read()) + mainResult = (rdr.ToDynamic() as object).Map(types[0]); + else + mainResult = null; + } + } + else + mainResult = cmd.ExecuteNonQuery(); + + #endregion Get main result + + #region Handle out params + + if (retParams != null) + { + Dictionary res = new Dictionary(); + + if (mainResult != null) + { + if (mainResult == DBNull.Value) + res.Add(binder.Name, null); + else + res.Add(binder.Name, mainResult); + } + + foreach (KeyValuePair pos in retParams) + res.Add(pos.Key, ((IDbDataParameter)cmd.Parameters[pos.Value]).Value); + + if (types.Count > 1) + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(types[1]); + + if (mapper != null) + result = mapper.Create(res.ToDynamic()); + else + result = res.ToDynamic(); + } + else + result = res.ToDynamic(); + } + else + result = mainResult; + + #endregion Handle out params + } + + return true; + } + + /// Performs application-defined tasks associated with + /// freeing, releasing, or resetting unmanaged resources. + public void Dispose() + { + } + } +} \ No newline at end of file diff --git a/DynamORM/DynamicQueryException.cs b/DynamORM/DynamicQueryException.cs index 3ca0783..a1487a6 100644 --- a/DynamORM/DynamicQueryException.cs +++ b/DynamORM/DynamicQueryException.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicSchemaColumn.cs b/DynamORM/DynamicSchemaColumn.cs index 9f29d47..767b7bd 100644 --- a/DynamORM/DynamicSchemaColumn.cs +++ b/DynamORM/DynamicSchemaColumn.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicTable.cs b/DynamORM/DynamicTable.cs index 955979d..3c9ade7 100644 --- a/DynamORM/DynamicTable.cs +++ b/DynamORM/DynamicTable.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/DynamicTransaction.cs b/DynamORM/DynamicTransaction.cs index 1628de6..8519762 100644 --- a/DynamORM/DynamicTransaction.cs +++ b/DynamORM/DynamicTransaction.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/CollectionComparer.cs b/DynamORM/Helpers/CollectionComparer.cs index 39f79cf..1c82fca 100644 --- a/DynamORM/Helpers/CollectionComparer.cs +++ b/DynamORM/Helpers/CollectionComparer.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/Dynamics/DynamicParser.cs b/DynamORM/Helpers/Dynamics/DynamicParser.cs index a7ff47c..e316004 100644 --- a/DynamORM/Helpers/Dynamics/DynamicParser.cs +++ b/DynamORM/Helpers/Dynamics/DynamicParser.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * This code file is based on Kerosene ORM solution for parsing dynamic diff --git a/DynamORM/Helpers/Dynamics/DynamicProxy.cs b/DynamORM/Helpers/Dynamics/DynamicProxy.cs index 0b0d1a9..86cbef8 100644 --- a/DynamORM/Helpers/Dynamics/DynamicProxy.cs +++ b/DynamORM/Helpers/Dynamics/DynamicProxy.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/FrameworkTools.cs b/DynamORM/Helpers/FrameworkTools.cs index 5f006a2..d79d03a 100644 --- a/DynamORM/Helpers/FrameworkTools.cs +++ b/DynamORM/Helpers/FrameworkTools.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/IExtendedDisposable.cs b/DynamORM/Helpers/IExtendedDisposable.cs index 562d146..8b0f802 100644 --- a/DynamORM/Helpers/IExtendedDisposable.cs +++ b/DynamORM/Helpers/IExtendedDisposable.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/IFinalizerDisposable.cs b/DynamORM/Helpers/IFinalizerDisposable.cs index 5bf1ced..d53c6d4 100644 --- a/DynamORM/Helpers/IFinalizerDisposable.cs +++ b/DynamORM/Helpers/IFinalizerDisposable.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/StringExtensions.cs b/DynamORM/Helpers/StringExtensions.cs index 78a20eb..a942b1c 100644 --- a/DynamORM/Helpers/StringExtensions.cs +++ b/DynamORM/Helpers/StringExtensions.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Helpers/UnclassifiedExtensions.cs b/DynamORM/Helpers/UnclassifiedExtensions.cs index 1917059..51049bd 100644 --- a/DynamORM/Helpers/UnclassifiedExtensions.cs +++ b/DynamORM/Helpers/UnclassifiedExtensions.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Mapper/ColumnAttribute.cs b/DynamORM/Mapper/ColumnAttribute.cs index 0050de4..7fbd777 100644 --- a/DynamORM/Mapper/ColumnAttribute.cs +++ b/DynamORM/Mapper/ColumnAttribute.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Mapper/DynamicCast.cs b/DynamORM/Mapper/DynamicCast.cs new file mode 100644 index 0000000..1bd75ba --- /dev/null +++ b/DynamORM/Mapper/DynamicCast.cs @@ -0,0 +1,120 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Concurrent; +using System.Linq.Expressions; +using System.Runtime.CompilerServices; + +namespace DynamORM.Mapper +{ + /// Type cast helper. + public static class DynamicCast + { + /// Gets the default value. + /// The type. + /// Default instance. + public static object GetDefaultValue(this Type type) + { + return type.IsValueType ? TypeDefaults.GetOrAdd(type, t => Activator.CreateInstance(t)) : null; + } + + /// Casts the object to this type. + /// The type to which cast value. + /// The value to cast. + /// Value casted to new type. + public static object CastObject(this Type type, object val) + { + return GetConverter(type, val)(val); + } + + private static readonly ConcurrentDictionary TypeDefaults = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary> TypeAsCasts = new ConcurrentDictionary>(); + private static readonly ConcurrentDictionary> TypeConvert = new ConcurrentDictionary>(); + private static readonly ParameterExpression ConvParameter = Expression.Parameter(typeof(object), "val"); + + [MethodImpl(MethodImplOptions.Synchronized)] + private static Func GetConverter(Type targetType, object val) + { + Func fn; + + if (!targetType.IsValueType && !val.GetType().IsValueType) + { + if (!TypeAsCasts.TryGetValue(targetType, out fn)) + { + UnaryExpression instanceCast = Expression.TypeAs(ConvParameter, targetType); + + fn = Expression.Lambda>(Expression.TypeAs(instanceCast, typeof(object)), ConvParameter).Compile(); + TypeAsCasts.AddOrUpdate(targetType, fn, (t, f) => fn); + } + } + else + { + var fromType = val != null ? val.GetType() : typeof(object); + var key = new PairOfTypes(fromType, targetType); + if (TypeConvert.TryGetValue(key, out fn)) + return fn; + + fn = (Func)Expression.Lambda(Expression.Convert(Expression.Convert(Expression.Convert(ConvParameter, fromType), targetType), typeof(object)), ConvParameter).Compile(); + TypeConvert.AddOrUpdate(key, fn, (t, f) => fn); + } + + return fn; + } + + private class PairOfTypes + { + private readonly Type _first; + private readonly Type _second; + + public PairOfTypes(Type first, Type second) + { + this._first = first; + this._second = second; + } + + public override int GetHashCode() + { + return (31 * _first.GetHashCode()) + _second.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj == this) + return true; + + var other = obj as PairOfTypes; + if (other == null) + return false; + + return _first.Equals(other._first) + && _second.Equals(other._second); + } + } + } +} \ No newline at end of file diff --git a/DynamORM/Mapper/DynamicMapperCache.cs b/DynamORM/Mapper/DynamicMapperCache.cs index 3ae3688..59b08c7 100644 --- a/DynamORM/Mapper/DynamicMapperCache.cs +++ b/DynamORM/Mapper/DynamicMapperCache.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Mapper/DynamicPropertyInvoker.cs b/DynamORM/Mapper/DynamicPropertyInvoker.cs index c83589f..9fb14ae 100644 --- a/DynamORM/Mapper/DynamicPropertyInvoker.cs +++ b/DynamORM/Mapper/DynamicPropertyInvoker.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Mapper/DynamicTypeMap.cs b/DynamORM/Mapper/DynamicTypeMap.cs index 4868f12..f141c4f 100644 --- a/DynamORM/Mapper/DynamicTypeMap.cs +++ b/DynamORM/Mapper/DynamicTypeMap.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Mapper/IgnoreAttribute.cs b/DynamORM/Mapper/IgnoreAttribute.cs index e173737..fe4e917 100644 --- a/DynamORM/Mapper/IgnoreAttribute.cs +++ b/DynamORM/Mapper/IgnoreAttribute.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Mapper/TableAttribute.cs b/DynamORM/Mapper/TableAttribute.cs index 66f21b5..dcce1c4 100644 --- a/DynamORM/Mapper/TableAttribute.cs +++ b/DynamORM/Mapper/TableAttribute.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/DynamORM/Properties/AssemblyInfo.cs b/DynamORM/Properties/AssemblyInfo.cs index 81c6c10..9d9dd14 100644 --- a/DynamORM/Properties/AssemblyInfo.cs +++ b/DynamORM/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ /* * DynamORM - Dynamic Object-Relational Mapping library. - * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) + * Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/Tester/Program.cs b/Tester/Program.cs index e48dd62..365f165 100644 --- a/Tester/Program.cs +++ b/Tester/Program.cs @@ -1,222 +1,46 @@ using System; -using System.Linq; -using DynamORM; using DynamORM.Mapper; -using System.Collections.Generic; -using System.Dynamic; namespace Tester { internal class Program { - [Table(Name = "mom_Sessions")] - internal class Session - { - [Column(IsKey = true)] - public virtual Guid ms_id { get; set; } - - [Column] - public virtual Guid ms_mus_id { get; set; } - - [Column] - public virtual long ms_last_activity { get; set; } - - [Column] - public virtual int ms_type { get; set; } - - [Column] - public virtual string ms_desc { get; set; } - - [Ignore] - public virtual string ms_did { get; set; } - } - private static DynamORM.DynamicDatabase GetORM() { - //return new DynamORM.DynamicDatabase(System.Data.SqlClient.SqlClientFactory.Instance, - // "packet size=4096;User Id=sa;Password=sa123;data source=192.168.1.9,1433;initial catalog=MOM_SIERPC_WMS_TEST;", + return new DynamORM.DynamicDatabase(System.Data.SqlClient.SqlClientFactory.Instance, + "packet size=4096;User Id=sa;Password=Sa123;data source=192.168.1.9,1434;initial catalog=MAH_Melle-GAGARIN;", + DynamORM.DynamicDatabaseOptions.SingleConnection | DynamORM.DynamicDatabaseOptions.SingleTransaction | DynamORM.DynamicDatabaseOptions.SupportStoredProcedures | + DynamORM.DynamicDatabaseOptions.SupportSchema | DynamORM.DynamicDatabaseOptions.SupportTop); + + //return new DynamORM.DynamicDatabase(System.Data.SQLite.SQLiteFactory.Instance, + // "Data Source=test.db3;", // DynamORM.DynamicDatabaseOptions.SingleConnection | DynamORM.DynamicDatabaseOptions.SingleTransaction | - // DynamORM.DynamicDatabaseOptions.SupportSchema | DynamORM.DynamicDatabaseOptions.SupportTop); - return new DynamORM.DynamicDatabase(System.Data.SQLite.SQLiteFactory.Instance, - "Data Source=test.db3;", - DynamORM.DynamicDatabaseOptions.SingleConnection | DynamORM.DynamicDatabaseOptions.SingleTransaction | - DynamORM.DynamicDatabaseOptions.SupportSchema | DynamORM.DynamicDatabaseOptions.SupportLimitOffset); + // DynamORM.DynamicDatabaseOptions.SupportSchema | DynamORM.DynamicDatabaseOptions.SupportLimitOffset); + } + + public class ProcResult + { + [Column("sp_Test_Scalar_In_Out")] + public Guid Result { get; set; } + + [Column("outp")] + public Guid Output { get; set; } } private static void Main(string[] args) { using (var db = GetORM()) - using (var con = db.Open()) - using (var cmd = con.CreateCommand()) - new List() - { - @"CREATE TABLE IF NOT EXISTS Test(id int NOT NULL PRIMARY KEY, val text);", - @"DELETE FROM Test;", - @"INSERT INTO Test VALUES(1, 'Test');", - }.ForEach(x => - cmd.SetCommand(x) - .ExecuteNonQuery()); - - Console.Out.WriteLine("Press ENTER to launch bombardment... or q and ENTER to quit."); - while (Console.In.ReadLine() != "q") { - Console.Out.WriteLine("Bombardment..."); + Guid res1 = db.Procedures.sp_Test_Scalar(); + object res2 = db.Procedures.sp_Test_NonScalar(); + object res3 = db.Procedures.sp_Test_Scalar_In_Out(inp: Guid.NewGuid(), out_outp: Guid.Empty); + ProcResult res4 = db.Procedures.sp_Test_Scalar_In_Out(inp: Guid.NewGuid(), out_outp: Guid.Empty); - long membefore = GC.GetTotalMemory(true); - - BombsAway(); - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Mem Before: {0}, Mem After: {1}. Done.", membefore, GC.GetTotalMemory(true)); + Console.Out.WriteLine(res1); + Console.Out.WriteLine(res2); + Console.Out.WriteLine(res3); + Console.Out.WriteLine(res4.Output); } } - - private static void BombsAway() - { - string test_str = string.Empty; - - /*for (int y = 0; y < 10; y++) - { - string val = null; - for (int i = 0; i < 1000; i++) - { - dynamic o = new ExpandoObject(); - o.Test = "123"; - o.Test2 = 123; - o.Test3 = true; - o.Test4 = (object)null; - - val = o.Test; - val = o.Test2.ToString(); - } - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [ExpandoObject only], Mem: {0}", GC.GetTotalMemory(true)); - } - - for (int y = 0; y < 10; y++) - { - string val = null; - - for (int i = 0; i < 1000; i++) - { - dynamic o = new ExpandoObject(); - var d = o as IDictionary; - d.Add("Test", "123"); - d.Add("Test2", 123); - d.Add("Test3", true); - d.Add("Test4", null); - - val = o.Test; - val = o.Test2.ToString(); - } - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [ExpandoObject as Dict], Mem: {0}", GC.GetTotalMemory(true)); - }*/ - - /*for (int y = 0; y < 10; y++) - { - Func f = x => x.To == 0; - for (int i = 0; i < 1000; i++) - using (var p = DynamORM.Helpers.Dynamics.DynamicParser.Parse(f)) - test_str = p.ToString(); - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: {0}, Mem: {1}", test_str, GC.GetTotalMemory(true)); - }*/ - - for (int y = 0; y < 10; y++) - { - using (var dbt = GetORM()) - using (dbt.Table("Test")) - ; - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [Create and destroy ORM], Mem: {0}", GC.GetTotalMemory(true)); - } - - //using (var db = GetORM()) - { - for (int y = 0; y < 5; y++) - { - using (var db = GetORM()) - for (int i = 0; i < 1000; i++) - test_str = ((int)db.Table("Test").Scalar("SELECT id FROM Test;")).ToString(); - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [db.Table(\"Test\").Scalar(\"SELECT id FROM Test;\")] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true)); - } - - for (int y = 0; y < 5; y++) - { - using (var db = GetORM()) - for (int i = 0; i < 1000; i++) - test_str = ((int)db.Table("Test").Scalar(columns: "id")).ToString(); - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [db.Table(\"Test\").Scalar(columns: \"id\")] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true)); - } - - for (int y = 0; y < 5; y++) - { - using (var db = GetORM()) - for (int i = 0; i < 1000; i++) - test_str = db.From(x => x.Test.As(x.t)).Where(t => t.id == 1).ToList().First().val; - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [db.From(x => x.Test.As(x.t)).Where(t => t.id == 1).ToList().First().val] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true)); - } - - for (int y = 0; y < 5; y++) - { - using (var db = GetORM()) - for (int i = 0; i < 1000; i++) - test_str = ((int)db.From(x => x.Test.As(x.t)).Where(t => t.id == 1).Select(t => t.id).Scalar()).ToString(); - - GC.WaitForPendingFinalizers(); - GC.Collect(); - - Console.Out.WriteLine("Expr: [db.From(x => x.Test.As(x.t)).Where(t => t.id == 1).Select(t => t.id).Scalar()] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true)); - } - } - - /*for (int i = 0; i < 1000; i++) - using (var db = GetORM()) - { - //var session = db.From(x => x.mom_Sessions.As(x.s)) - // .Where(s => s.ms_id == Guid.Empty && s.ms_mus_id == Guid.Empty) - // .Execute() - // .FirstOrDefault(); - var session = db.From(x => x.mom_Sessions.As(x.s)) - .Where(s => s.ms_id == Guid.Empty && s.ms_mus_id == Guid.Empty) - .Execute() - .FirstOrDefault(); - - //db.Table("mom_Sessions").Delete() - // .Where("ms_id", Guid.Empty) - // .Where("ms_mus_id", Guid.Empty) - // .Execute(); - - //var session = (db.Table().Query("SELECT * FROM mom_Sessions WHERE ms_id = @0 AND ms_mus_id = @1", Guid.Empty, Guid.Empty) - // as IEnumerable).FirstOrDefault(); - }*/ - } } } \ No newline at end of file