diff --git a/DynamORM.Tests/Modify/ParserTests.cs b/DynamORM.Tests/Modify/ParserTests.cs index 72aef75..c650a9d 100644 --- a/DynamORM.Tests/Modify/ParserTests.cs +++ b/DynamORM.Tests/Modify/ParserTests.cs @@ -27,6 +27,7 @@ */ using System.Linq; +using DynamORM.Builders; using DynamORM.Builders.Implementation; using NUnit.Framework; @@ -55,13 +56,15 @@ namespace DynamORM.Tests.Modify DestroyTestDatabase(); } + #region Insert + /// /// Tests the basic insert. /// [Test] - public void TestBasicInsert() + public void TestInsertBasic() { - var cmd = new DynamicInsertQueryBuilder(Database, "Users"); + IDynamicInsertQueryBuilder cmd = new DynamicInsertQueryBuilder(Database, "Users"); cmd.Insert(x => x.Users.Code = "001", x => x.Users.Name = "Admin", x => x.Users.IsAdmin = 1); @@ -75,7 +78,7 @@ namespace DynamORM.Tests.Modify [Test] public void TestInsertSubQuery() { - var cmd = new DynamicInsertQueryBuilder(Database, "Users"); + IDynamicInsertQueryBuilder cmd = new DynamicInsertQueryBuilder(Database, "Users"); cmd.Insert(x => x.Code = "001", x => x.Name = "Admin", x => x.IsAdmin = x(cmd .SubQuery(a => a.AccessRights.As(a.a)) @@ -90,9 +93,9 @@ namespace DynamORM.Tests.Modify /// Tests the basic insert using object. /// [Test] - public void TestBasicInsertObject() + public void TestInsertBasicObject() { - var cmd = new DynamicInsertQueryBuilder(Database, "Users"); + IDynamicInsertQueryBuilder cmd = new DynamicInsertQueryBuilder(Database, "Users"); cmd.Insert(x => new { Code = "001", Name = "Admin", IsAdmin = 1 }); @@ -106,7 +109,7 @@ namespace DynamORM.Tests.Modify [Test] public void TestInsertSubQueryObject() { - var cmd = new DynamicInsertQueryBuilder(Database, "Users"); + IDynamicInsertQueryBuilder cmd = new DynamicInsertQueryBuilder(Database, "Users"); cmd.Insert(x => new { @@ -121,5 +124,81 @@ namespace DynamORM.Tests.Modify Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0}, (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = [${1}])))", string.Join(", ", cmd.Parameters.Keys.Take(2).Select(p => string.Format("[${0}]", p))), cmd.Parameters.Keys.Last()), cmd.CommandText()); } + + #endregion Insert + + #region Update + + /// + /// Tests the basic update. + /// + [Test] + public void TestUpdateBasic() + { + IDynamicUpdateQueryBuilder cmd = new DynamicUpdateQueryBuilder(Database, "Users"); + + cmd.Values(x => x.Users.Code = "001", x => x.Users.Name = "Admin", x => x.Users.IsAdmin = 1) + .Where(x => x.Users.Id_User == 1); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = [${2}] WHERE (""Users"".""Id_User"" = [${3}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], cmd.Parameters.Keys.ToArray()[3]), cmd.CommandText()); + } + + /// + /// Tests the insert with sub query. + /// + [Test] + public void TestUpdateSubQuery() + { + IDynamicUpdateQueryBuilder cmd = new DynamicUpdateQueryBuilder(Database, "Users"); + + cmd.Values(x => x.Users.Code = "001", x => x.Users.Name = "Admin", x => x.Users.IsAdmin = x(cmd + .SubQuery(a => a.AccessRights.As(a.a)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == a.Users.Id_User))) + .Where(x => x.Users.Id_User == 1); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = ""Users"".""Id_User"")) WHERE (""Users"".""Id_User"" = [${2}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + /// + /// Tests the basic insert using object. + /// + [Test] + public void TestUpdateBasicObject() + { + IDynamicUpdateQueryBuilder cmd = new DynamicUpdateQueryBuilder(Database, "Users"); + + cmd.Values(x => new { Code = "001", Name = "Admin", IsAdmin = 1 }) + .Where(x => new { Id_User = 1 }); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = [${2}] WHERE (""Id_User"" = [${3}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], cmd.Parameters.Keys.ToArray()[3]), cmd.CommandText()); + } + + /// + /// Tests the basic insert using object. + /// + [Test] + public void TestUpdateSubQueryObject() + { + IDynamicUpdateQueryBuilder cmd = new DynamicUpdateQueryBuilder(Database, "Users"); + + cmd.Values(x => new + { + Code = "001", + Name = "Admin", + IsAdmin = x(cmd + .SubQuery(a => a.AccessRights.As(a.a)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == a.Users.Id_User)) + }).Where(x => new { Id_User = 1 }); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = ""Users"".""Id_User"")) WHERE (""Id_User"" = [${2}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + #endregion Update } } \ No newline at end of file diff --git a/DynamORM.Tests/Select/DynamicAccessTests.cs b/DynamORM.Tests/Select/DynamicAccessTests.cs index 371816f..adfb77b 100644 --- a/DynamORM.Tests/Select/DynamicAccessTests.cs +++ b/DynamORM.Tests/Select/DynamicAccessTests.cs @@ -436,29 +436,23 @@ namespace DynamORM.Tests.Select Assert.AreEqual(exp.last, o.last); } - /// Test dynamic duplicate column name ocurrance. + /// Test dynamic duplicate column name occurrence. [Test] public void TestDuplicateColumnNameException() { Assert.Throws(() => GetTestBuilder() .Where(x => x.id == 19) - .Select(x => new { id = x.id, first = x.first, last = x.last }) + .Select(x => new + { + id = x.id, + first = x.first, + last = x.last, + }) .Select(x => x.last.As(x.first)) // Make last be first .Execute() .First()); } - [Test] - public void TestEmptyColumnName() - { - var v = GetTestBuilder() - .Select(x => x.first, x => x.Count(x.first)) - .GroupBy(x => x.first) - .OrderBy(x => x.Desc(2)) - .Execute() - .ToList(); - } - #endregion Select #region Where diff --git a/DynamORM.Tests/Select/ParserTests.cs b/DynamORM.Tests/Select/ParserTests.cs index 2d2f4e1..9e18c4f 100644 --- a/DynamORM.Tests/Select/ParserTests.cs +++ b/DynamORM.Tests/Select/ParserTests.cs @@ -326,6 +326,21 @@ namespace DynamORM.Tests.Select Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr INNER JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); } + /// + /// Tests inner join method with aliases mix. + /// + [Test] + public void TestInnerJoin2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(usr => usr.Inner().dbo.UserClients.AS(usr.uc).On(usr.Id_User == usr.uc.User_Id && usr.uc.Users != null)) + .Select(usr => usr.All(), uc => uc.Users); + + Assert.AreEqual(string.Format("SELECT usr.*, uc.\"Users\" FROM \"dbo\".\"Users\" AS usr INNER JOIN \"dbo\".\"UserClients\" AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Users\" IS NOT NULL))"), cmd.CommandText()); + } + /// /// Tests left outer join method. /// @@ -496,6 +511,20 @@ namespace DynamORM.Tests.Select Assert.AreEqual("SELECT u.\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\" AS u", cmd.CommandText()); } + /// + /// Tests select field with alias. + /// + [Test] + public void TestSelectFieldAlias4() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.u)) + .Select(u => u.UserName.As(u.u.Name)); + + Assert.AreEqual("SELECT u.\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\" AS u", cmd.CommandText()); + } + /// /// Tests select aggregate field with alias (Sum). /// diff --git a/DynamORM/Builders/IDynamicSelectQueryBuilder.cs b/DynamORM/Builders/IDynamicSelectQueryBuilder.cs index b8194ba..00091d8 100644 --- a/DynamORM/Builders/IDynamicSelectQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicSelectQueryBuilder.cs @@ -1,4 +1,32 @@ -using System; +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012, 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.Generic; namespace DynamORM.Builders diff --git a/DynamORM/Builders/ITableInfo.cs b/DynamORM/Builders/ITableInfo.cs index 03bb867..df54153 100644 --- a/DynamORM/Builders/ITableInfo.cs +++ b/DynamORM/Builders/ITableInfo.cs @@ -1,8 +1,30 @@ -// ----------------------------------------------------------------------- -// -// TODO: Update copyright text. -// -// ----------------------------------------------------------------------- +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012, 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.Collections.Generic; diff --git a/DynamORM/DynamORM.csproj b/DynamORM/DynamORM.csproj index a9a5483..24f374c 100644 --- a/DynamORM/DynamORM.csproj +++ b/DynamORM/DynamORM.csproj @@ -66,6 +66,7 @@ + diff --git a/DynamORM/DynamicCommand.cs b/DynamORM/DynamicCommand.cs index 8dcceba..3b2da24 100644 --- a/DynamORM/DynamicCommand.cs +++ b/DynamORM/DynamicCommand.cs @@ -28,11 +28,12 @@ using System; using System.Data; +using DynamORM.Helpers; namespace DynamORM { /// Helper class to easy manage command. - public class DynamicCommand : IDbCommand + public class DynamicCommand : IDbCommand, IExtendedDisposable { private IDbCommand _command; private int? _commandTimeout = null; @@ -45,6 +46,7 @@ namespace DynamORM /// The database manager. internal DynamicCommand(DynamicConnection con, DynamicDatabase db) { + IsDisposed = false; _con = con; _db = db; @@ -65,6 +67,7 @@ namespace DynamORM /// Used internally to create command without context. internal DynamicCommand(DynamicDatabase db) { + IsDisposed = false; _db = db; _command = db.Provider.CreateCommand(); } @@ -152,7 +155,14 @@ namespace DynamORM /// The number of rows affected. public int ExecuteNonQuery() { - return PrepareForExecution().ExecuteNonQuery(); + try + { + return PrepareForExecution().ExecuteNonQuery(); + } + catch (Exception ex) + { + throw new DynamicQueryException(ex, this); + } } /// Executes the @@ -164,7 +174,14 @@ namespace DynamORM /// An object. public IDataReader ExecuteReader(CommandBehavior behavior) { - return PrepareForExecution().ExecuteReader(behavior); + try + { + return PrepareForExecution().ExecuteReader(behavior); + } + catch (Exception ex) + { + throw new DynamicQueryException(ex, this); + } } /// Executes the @@ -173,7 +190,14 @@ namespace DynamORM /// An object. public IDataReader ExecuteReader() { - return PrepareForExecution().ExecuteReader(); + try + { + return PrepareForExecution().ExecuteReader(); + } + catch (Exception ex) + { + throw new DynamicQueryException(ex, this); + } } /// Executes the query, and returns the first column of the @@ -182,7 +206,14 @@ namespace DynamORM /// The first column of the first row in the result set. public object ExecuteScalar() { - return PrepareForExecution().ExecuteScalar(); + try + { + return PrepareForExecution().ExecuteScalar(); + } + catch (Exception ex) + { + throw new DynamicQueryException(ex, this); + } } /// Gets the . @@ -194,7 +225,14 @@ namespace DynamORM /// Creates a prepared (or compiled) version of the command on the data source. public void Prepare() { - _command.Prepare(); + try + { + _command.Prepare(); + } + catch (Exception ex) + { + throw new DynamicQueryException("Error preparing command.", ex, this); + } } /// Gets or sets the transaction within which the Command @@ -214,7 +252,7 @@ namespace DynamORM #endregion IDbCommand Members - #region IDisposable Members + #region IExtendedDisposable Members /// Performs application-defined tasks associated with /// freeing, releasing, or resetting unmanaged resources. @@ -231,9 +269,14 @@ namespace DynamORM } _command.Dispose(); + + IsDisposed = true; } } - #endregion IDisposable Members + /// Gets a value indicating whether this instance is disposed. + public bool IsDisposed { get; private set; } + + #endregion IExtendedDisposable Members } } \ No newline at end of file diff --git a/DynamORM/DynamicConnection.cs b/DynamORM/DynamicConnection.cs index 8285b9b..2e4cb0a 100644 --- a/DynamORM/DynamicConnection.cs +++ b/DynamORM/DynamicConnection.cs @@ -28,13 +28,14 @@ using System; using System.Data; +using DynamORM.Helpers; namespace DynamORM { /// Connection wrapper. /// This class is only connection holder, connection is managed by /// instance. - public class DynamicConnection : IDbConnection, IDisposable + public class DynamicConnection : IDbConnection, IExtendedDisposable { private DynamicDatabase _db; private bool _singleTransaction; @@ -48,6 +49,7 @@ namespace DynamORM /// Are we using single transaction mode? I so... act correctly. internal DynamicConnection(DynamicDatabase db, IDbConnection con, bool singleTransaction) { + IsDisposed = false; _db = db; Connection = con; _singleTransaction = singleTransaction; @@ -147,11 +149,19 @@ namespace DynamORM #endregion IDbConnection Members + #region IExtendedDisposable Members + /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. public void Dispose() { _db.Close(Connection); + IsDisposed = true; } + + /// Gets a value indicating whether this instance is disposed. + public bool IsDisposed { get; private set; } + + #endregion IExtendedDisposable Members } } \ No newline at end of file diff --git a/DynamORM/DynamicDatabase.cs b/DynamORM/DynamicDatabase.cs index 6ddbbe9..c647451 100644 --- a/DynamORM/DynamicDatabase.cs +++ b/DynamORM/DynamicDatabase.cs @@ -40,7 +40,7 @@ using DynamORM.Mapper; namespace DynamORM { /// Dynamic database is a class responsible for managing database. - public class DynamicDatabase : IDisposable + public class DynamicDatabase : IExtendedDisposable { #region Internal fields and properties @@ -127,6 +127,7 @@ namespace DynamORM /// Connection options. public DynamicDatabase(DbProviderFactory provider, string connectionString, DynamicDatabaseOptions options) { + IsDisposed = false; _provider = provider; InitCommon(connectionString, options); @@ -137,6 +138,7 @@ namespace DynamORM /// Connection options. required. public DynamicDatabase(IDbConnection connection, DynamicDatabaseOptions options) { + IsDisposed = false; InitCommon(connection.ConnectionString, options); TransactionPool.Add(connection, new Stack()); @@ -643,7 +645,7 @@ namespace DynamORM #endregion Transaction - #region IDisposable Members + #region IExtendedDisposable Members /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. @@ -684,9 +686,13 @@ namespace DynamORM // Clear pools TransactionPool.Clear(); CommandsPool.Clear(); + IsDisposed = true; } } - #endregion IDisposable Members + /// Gets a value indicating whether this instance is disposed. + public bool IsDisposed { get; private set; } + + #endregion IExtendedDisposable Members } } \ No newline at end of file diff --git a/DynamORM/DynamicExtensions.cs b/DynamORM/DynamicExtensions.cs index 5487b65..15e4245 100644 --- a/DynamORM/DynamicExtensions.cs +++ b/DynamORM/DynamicExtensions.cs @@ -798,9 +798,9 @@ namespace DynamORM #region Dynamic extensions /// Turns an to a Dynamic list of things. - /// Reader from which read data.. + /// Reader from which read data. /// List of things. - public static List ToDynamicList(this IDataReader r) + public static List ToList(this IDataReader r) { var result = new List(); @@ -810,6 +810,23 @@ namespace DynamORM return result; } + /// Turns an to a Dynamic list of things. + /// Ready to execute builder. + /// List of things. + public static List ToList(this IDynamicSelectQueryBuilder b) + { + return b.Execute().ToList(); + } + + /// Turns an to a Dynamic list of things with specified type. + /// Type of object to map on. + /// Ready to execute builder. + /// List of things. + public static List ToList(this IDynamicSelectQueryBuilder b) where T : class + { + return b.Execute().ToList(); + } + /// Turns the dictionary into an ExpandoObject. /// Dictionary to convert. /// Converted dictionary. diff --git a/DynamORM/DynamicQueryException.cs b/DynamORM/DynamicQueryException.cs new file mode 100644 index 0000000..915f2fa --- /dev/null +++ b/DynamORM/DynamicQueryException.cs @@ -0,0 +1,128 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012, 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.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.") + { + if (command != null) + { + var sb = new StringBuilder(); + command.Dump(sb); + Command = sb.ToString(); + } + } + + /// Initializes a new instance of the + /// class. + /// The message. + /// The command which failed. + public DynamicQueryException(string message, IDbCommand command = null) + : base(message) + { + SetCommand(command); + } + + /// Initializes a new instance of the + /// class. + /// The inner exception. + /// The command which failed. + public DynamicQueryException(Exception innerException, IDbCommand command = null) + : base("Error executing command.", innerException) + { + SetCommand(command); + } + + /// Initializes a new instance of the + /// class. + /// The message. + /// The inner exception. + /// The command which failed. + public DynamicQueryException(string message, Exception innerException, IDbCommand command = null) + : base(message, innerException) + { + SetCommand(command); + } + + /// Initializes a new instance of the + /// class. + /// The + /// that holds the serialized object data about the exception being thrown. + /// The + /// that contains contextual information about the source or destination. + public DynamicQueryException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + Command = info.GetString("Command"); + } + + /// When overridden in a derived class, sets the + /// + /// with information about the exception. + /// The + /// that holds the serialized object data about the exception being thrown. + /// The + /// that contains contextual information about the source or destination. + /// + /// + /// + /// + 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/DynamicTable.cs b/DynamORM/DynamicTable.cs index 6ded5a4..d7fd75c 100644 --- a/DynamORM/DynamicTable.cs +++ b/DynamORM/DynamicTable.cs @@ -194,7 +194,7 @@ namespace DynamORM /// }); /// x.Delete(where: new { id = 14, code = 14 }); /// - public class DynamicTable : DynamicObject, IDisposable, ICloneable + public class DynamicTable : DynamicObject, IExtendedDisposable, ICloneable { private static HashSet _allowedCommands = new HashSet { @@ -243,6 +243,7 @@ namespace DynamORM /// Override keys in schema. public DynamicTable(DynamicDatabase database, string table = "", string owner = "", string[] keys = null) { + IsDisposed = false; Database = database; TableName = Database.StripName(table); OwnerName = Database.StripName(owner); @@ -260,15 +261,20 @@ namespace DynamORM if (type == null) throw new ArgumentNullException("type", "Type can't be null."); - Database = database; + IsDisposed = false; + Database = database; TableType = type; var mapper = DynamicMapperCache.GetMapper(type); if (mapper != null) + { TableName = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ? type.Name : mapper.Table.Name; + OwnerName = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ? + type.Name : mapper.Table.Name; + } BuildAndCacheSchema(keys); } @@ -995,7 +1001,7 @@ namespace DynamORM #endregion Universal Dynamic Invoker - #region IDisposable Members + #region IExtendedDisposable Members /// Performs application-defined tasks associated with /// freeing, releasing, or resetting unmanaged resources. @@ -1007,9 +1013,14 @@ namespace DynamORM Database.RemoveFromCache(this); Database = null; } + + IsDisposed = true; } - #endregion IDisposable Members + /// Gets a value indicating whether this instance is disposed. + public bool IsDisposed { get; private set; } + + #endregion IExtendedDisposable Members #region ICloneable Members diff --git a/DynamORM/DynamicTransaction.cs b/DynamORM/DynamicTransaction.cs index 09af02e..3bc7efb 100644 --- a/DynamORM/DynamicTransaction.cs +++ b/DynamORM/DynamicTransaction.cs @@ -28,11 +28,12 @@ using System; using System.Data; +using DynamORM.Helpers; namespace DynamORM { /// Helper class to easy manage transaction. - public class DynamicTransaction : IDbTransaction, IDisposable + public class DynamicTransaction : IDbTransaction, IExtendedDisposable { private DynamicDatabase _db; private DynamicConnection _con; @@ -48,6 +49,7 @@ namespace DynamORM /// This action is invoked when transaction is disposed. internal DynamicTransaction(DynamicDatabase db, DynamicConnection con, bool singleTransaction, IsolationLevel? il, Action disposed) { + IsDisposed = false; _db = db; _con = con; _singleTransaction = singleTransaction; @@ -125,6 +127,8 @@ namespace DynamORM /// Gets for this transaction. public IsolationLevel IsolationLevel { get; private set; } + #region IExtendedDisposable Members + /// Performs application-defined tasks associated with /// freeing, releasing, or resetting unmanaged resources. public void Dispose() @@ -133,6 +137,13 @@ namespace DynamORM if (_disposed != null) _disposed(); + + IsDisposed = true; } + + /// Gets a value indicating whether this instance is disposed. + public bool IsDisposed { get; private set; } + + #endregion IExtendedDisposable Members } } \ No newline at end of file