diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs index 6837c95..4507f20 100644 --- a/AmalgamationTool/DynamORM.Amalgamation.cs +++ b/AmalgamationTool/DynamORM.Amalgamation.cs @@ -3027,6 +3027,16 @@ namespace DynamORM #endregion Generic Execution + /// Dump command into string. + /// Command to dump. + /// Returns dumped instance in string form. + public static string DumpToString(this IDbCommand command) + { + var sb = new StringBuilder(); + command.Dump(sb); + return sb.ToString(); + } + /// Dump command into text writer. /// Command to dump. /// Builder to which write output. @@ -3705,21 +3715,12 @@ namespace DynamORM /// Dynamic query exception. public class DynamicQueryException : Exception, ISerializable { - /// Gets the dumped command which failed. - public string Command { get; private set; } - /// Initializes a new instance of the /// class. /// The command which failed. public DynamicQueryException(IDbCommand command = null) - : base("Error executing command.") + : base(string.Format("Error executing command.{0}{1}", Environment.NewLine, command != null ? command.DumpToString() : string.Empty)) { - if (command != null) - { - var sb = new StringBuilder(); - command.Dump(sb); - Command = sb.ToString(); - } } /// Initializes a new instance of the @@ -3727,9 +3728,8 @@ namespace DynamORM /// The message. /// The command which failed. public DynamicQueryException(string message, IDbCommand command = null) - : base(message) + : base(string.Format("{0}{1}{2}", message, Environment.NewLine, command != null ? command.DumpToString() : string.Empty)) { - SetCommand(command); } /// Initializes a new instance of the @@ -3737,9 +3737,8 @@ namespace DynamORM /// The inner exception. /// The command which failed. public DynamicQueryException(Exception innerException, IDbCommand command = null) - : base("Error executing command.", innerException) + : base(string.Format("Error executing command.{0}{1}", Environment.NewLine, command != null ? command.DumpToString() : string.Empty), innerException) { - SetCommand(command); } /// Initializes a new instance of the @@ -3748,9 +3747,8 @@ namespace DynamORM /// The inner exception. /// The command which failed. public DynamicQueryException(string message, Exception innerException, IDbCommand command = null) - : base(message, innerException) + : base(string.Format("{0}{1}{2}", message, Environment.NewLine, command != null ? command.DumpToString() : string.Empty), innerException) { - SetCommand(command); } /// Initializes a new instance of the @@ -3762,7 +3760,6 @@ namespace DynamORM public DynamicQueryException(SerializationInfo info, StreamingContext context) : base(info, context) { - Command = info.GetString("Command"); } /// When overridden in a derived class, sets the @@ -3779,19 +3776,6 @@ namespace DynamORM public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); - - if (!string.IsNullOrEmpty(Command)) - info.AddValue("Command", Command); - } - - private void SetCommand(IDbCommand command) - { - if (command != null && (!(command is DynamicCommand) || ((command is DynamicCommand) && !(command as DynamicCommand).IsDisposed))) - { - var sb = new StringBuilder(); - command.Dump(sb); - Command = sb.ToString(); - } } } @@ -10168,7 +10152,7 @@ namespace DynamORM { var prop = _properties.TryGetValue(binder.Name); - if (prop != null && prop.Set != null) + if (prop != null && prop.Setter != null) { prop.Set(_proxy, value); return true; @@ -10505,7 +10489,7 @@ namespace DynamORM public Func Get { get; private set; } /// Gets value setter. - public Action Set { get; private set; } + public Action Setter { get; private set; } /// Gets name of property. public string Name { get; private set; } @@ -10534,7 +10518,7 @@ namespace DynamORM Get = CreateGetter(property); if (property.CanWrite) - Set = CreateSetter(property); + Setter = CreateSetter(property); } private Func CreateGetter(PropertyInfo property) @@ -10569,6 +10553,48 @@ namespace DynamORM objParm, valueParm).Compile(); } + /// Sets the specified value to destination object. + /// The destination object. + /// The value. + public void Set(object dest, object val) + { + Type type = Nullable.GetUnderlyingType(Type) ?? Type; + bool nullable = Type.IsGenericType && Type.GetGenericTypeDefinition() == typeof(Nullable<>); + + try + { + if (val == null && type.IsValueType) + { + if (nullable) + Setter(dest, null); + else + Setter(dest, Activator.CreateInstance(Type)); + } + else if ((val == null && !type.IsValueType) || (val != null && type == val.GetType())) + Setter(dest, val); + else if (type.IsEnum && val.GetType().IsValueType) + Setter(dest, Enum.ToObject(type, val)); + else if (type.IsEnum) + Setter(dest, Enum.Parse(type, val.ToString())); + else if (Type == typeof(string) && val.GetType() == typeof(Guid)) + Setter(dest, val.ToString()); + else if (Type == typeof(Guid) && val.GetType() == typeof(string)) + { + Guid g; + Setter(dest, Guid.TryParse((string)val, out g) ? g : Guid.Empty); + } + else + Setter(dest, Convert.ChangeType(val, type)); + } + catch (Exception ex) + { + throw new InvalidCastException( + string.Format("Error trying to convert value '{0}' of type '{1}' to value of type '{2}{3}' in object of type '{4}'", + val.ToString(), val.GetType(), type.FullName, nullable ? "(NULLABLE)" : string.Empty, dest.GetType().FullName), + ex); + } + } + #region Type command cache internal ParameterSpec InsertCommandParameter { get; set; } @@ -10677,7 +10703,7 @@ namespace DynamORM foreach (var item in source.ToDictionary()) { if (ColumnsMap.TryGetValue(item.Key.ToLower(), out dpi) && item.Value != null) - if (dpi.Set != null) + if (dpi.Setter != null) dpi.Set(destination, item.Value); } diff --git a/DynamORM/DynamicExtensions.cs b/DynamORM/DynamicExtensions.cs index eda5b1c..8c25455 100644 --- a/DynamORM/DynamicExtensions.cs +++ b/DynamORM/DynamicExtensions.cs @@ -731,6 +731,16 @@ namespace DynamORM #endregion Generic Execution + /// Dump command into string. + /// Command to dump. + /// Returns dumped instance in string form. + public static string DumpToString(this IDbCommand command) + { + var sb = new StringBuilder(); + command.Dump(sb); + return sb.ToString(); + } + /// Dump command into text writer. /// Command to dump. /// Builder to which write output. diff --git a/DynamORM/DynamicQueryException.cs b/DynamORM/DynamicQueryException.cs index 915f2fa..80b62c8 100644 --- a/DynamORM/DynamicQueryException.cs +++ b/DynamORM/DynamicQueryException.cs @@ -29,28 +29,18 @@ using System; using System.Data; using System.Runtime.Serialization; -using System.Text; namespace DynamORM { /// Dynamic query exception. public class DynamicQueryException : Exception, ISerializable { - /// Gets the dumped command which failed. - public string Command { get; private set; } - /// Initializes a new instance of the /// class. /// The command which failed. public DynamicQueryException(IDbCommand command = null) - : base("Error executing command.") + : base(string.Format("Error executing command.{0}{1}", Environment.NewLine, command != null ? command.DumpToString() : string.Empty)) { - if (command != null) - { - var sb = new StringBuilder(); - command.Dump(sb); - Command = sb.ToString(); - } } /// Initializes a new instance of the @@ -58,9 +48,8 @@ namespace DynamORM /// The message. /// The command which failed. public DynamicQueryException(string message, IDbCommand command = null) - : base(message) + : base(string.Format("{0}{1}{2}", message, Environment.NewLine, command != null ? command.DumpToString() : string.Empty)) { - SetCommand(command); } /// Initializes a new instance of the @@ -68,9 +57,8 @@ namespace DynamORM /// The inner exception. /// The command which failed. public DynamicQueryException(Exception innerException, IDbCommand command = null) - : base("Error executing command.", innerException) + : base(string.Format("Error executing command.{0}{1}", Environment.NewLine, command != null ? command.DumpToString() : string.Empty), innerException) { - SetCommand(command); } /// Initializes a new instance of the @@ -79,9 +67,8 @@ namespace DynamORM /// The inner exception. /// The command which failed. public DynamicQueryException(string message, Exception innerException, IDbCommand command = null) - : base(message, innerException) + : base(string.Format("{0}{1}{2}", message, Environment.NewLine, command != null ? command.DumpToString() : string.Empty), innerException) { - SetCommand(command); } /// Initializes a new instance of the @@ -93,7 +80,6 @@ namespace DynamORM public DynamicQueryException(SerializationInfo info, StreamingContext context) : base(info, context) { - Command = info.GetString("Command"); } /// When overridden in a derived class, sets the @@ -110,19 +96,6 @@ namespace DynamORM public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); - - if (!string.IsNullOrEmpty(Command)) - info.AddValue("Command", Command); - } - - private void SetCommand(IDbCommand command) - { - if (command != null && (!(command is DynamicCommand) || ((command is DynamicCommand) && !(command as DynamicCommand).IsDisposed))) - { - var sb = new StringBuilder(); - command.Dump(sb); - Command = sb.ToString(); - } } } } \ No newline at end of file diff --git a/DynamORM/Helpers/Dynamics/DynamicProxy.cs b/DynamORM/Helpers/Dynamics/DynamicProxy.cs index 5d4a242..5da028e 100644 --- a/DynamORM/Helpers/Dynamics/DynamicProxy.cs +++ b/DynamORM/Helpers/Dynamics/DynamicProxy.cs @@ -182,7 +182,7 @@ namespace DynamORM.Helpers.Dynamics { var prop = _properties.TryGetValue(binder.Name); - if (prop != null && prop.Set != null) + if (prop != null && prop.Setter != null) { prop.Set(_proxy, value); return true; diff --git a/DynamORM/Mapper/DynamicPropertyInvoker.cs b/DynamORM/Mapper/DynamicPropertyInvoker.cs index 95fc93f..96f873d 100644 --- a/DynamORM/Mapper/DynamicPropertyInvoker.cs +++ b/DynamORM/Mapper/DynamicPropertyInvoker.cs @@ -52,7 +52,7 @@ namespace DynamORM.Mapper public Func Get { get; private set; } /// Gets value setter. - public Action Set { get; private set; } + public Action Setter { get; private set; } /// Gets name of property. public string Name { get; private set; } @@ -81,7 +81,7 @@ namespace DynamORM.Mapper Get = CreateGetter(property); if (property.CanWrite) - Set = CreateSetter(property); + Setter = CreateSetter(property); } private Func CreateGetter(PropertyInfo property) @@ -116,6 +116,48 @@ namespace DynamORM.Mapper objParm, valueParm).Compile(); } + /// Sets the specified value to destination object. + /// The destination object. + /// The value. + public void Set(object dest, object val) + { + Type type = Nullable.GetUnderlyingType(Type) ?? Type; + bool nullable = Type.IsGenericType && Type.GetGenericTypeDefinition() == typeof(Nullable<>); + + try + { + if (val == null && type.IsValueType) + { + if (nullable) + Setter(dest, null); + else + Setter(dest, Activator.CreateInstance(Type)); + } + else if ((val == null && !type.IsValueType) || (val != null && type == val.GetType())) + Setter(dest, val); + else if (type.IsEnum && val.GetType().IsValueType) + Setter(dest, Enum.ToObject(type, val)); + else if (type.IsEnum) + Setter(dest, Enum.Parse(type, val.ToString())); + else if (Type == typeof(string) && val.GetType() == typeof(Guid)) + Setter(dest, val.ToString()); + else if (Type == typeof(Guid) && val.GetType() == typeof(string)) + { + Guid g; + Setter(dest, Guid.TryParse((string)val, out g) ? g : Guid.Empty); + } + else + Setter(dest, Convert.ChangeType(val, type)); + } + catch (Exception ex) + { + throw new InvalidCastException( + string.Format("Error trying to convert value '{0}' of type '{1}' to value of type '{2}{3}' in object of type '{4}'", + val.ToString(), val.GetType(), type.FullName, nullable ? "(NULLABLE)" : string.Empty, dest.GetType().FullName), + ex); + } + } + #region Type command cache internal ParameterSpec InsertCommandParameter { get; set; } diff --git a/DynamORM/Mapper/DynamicTypeMap.cs b/DynamORM/Mapper/DynamicTypeMap.cs index f34791d..658bd7a 100644 --- a/DynamORM/Mapper/DynamicTypeMap.cs +++ b/DynamORM/Mapper/DynamicTypeMap.cs @@ -129,7 +129,7 @@ namespace DynamORM.Mapper foreach (var item in source.ToDictionary()) { if (ColumnsMap.TryGetValue(item.Key.ToLower(), out dpi) && item.Value != null) - if (dpi.Set != null) + if (dpi.Setter != null) dpi.Set(destination, item.Value); }