diff --git a/DynamORM.Tests/Modify/ParserTests.cs b/DynamORM.Tests/Modify/ParserTests.cs index 5603885..72aef75 100644 --- a/DynamORM.Tests/Modify/ParserTests.cs +++ b/DynamORM.Tests/Modify/ParserTests.cs @@ -68,5 +68,58 @@ namespace DynamORM.Tests.Modify Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0})", string.Join(", ", cmd.Parameters.Keys.Select(p => string.Format("[${0}]", p)))), cmd.CommandText()); } + + /// + /// Tests the insert with sub query. + /// + [Test] + public void TestInsertSubQuery() + { + var 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)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == "001"))); + + 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()); + } + + /// + /// Tests the basic insert using object. + /// + [Test] + public void TestBasicInsertObject() + { + var cmd = new DynamicInsertQueryBuilder(Database, "Users"); + + cmd.Insert(x => new { Code = "001", Name = "Admin", IsAdmin = 1 }); + + Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0})", + string.Join(", ", cmd.Parameters.Keys.Select(p => string.Format("[${0}]", p)))), cmd.CommandText()); + } + + /// + /// Tests the insert using object with sub query. + /// + [Test] + public void TestInsertSubQueryObject() + { + var cmd = new DynamicInsertQueryBuilder(Database, "Users"); + + cmd.Insert(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 == "001")) + }); + + 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()); + } } } \ No newline at end of file diff --git a/DynamORM.Tests/Select/DynamicAccessTests.cs b/DynamORM.Tests/Select/DynamicAccessTests.cs index 223e569..371816f 100644 --- a/DynamORM.Tests/Select/DynamicAccessTests.cs +++ b/DynamORM.Tests/Select/DynamicAccessTests.cs @@ -436,6 +436,29 @@ namespace DynamORM.Tests.Select Assert.AreEqual(exp.last, o.last); } + /// Test dynamic duplicate column name ocurrance. + [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 => 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 7de7914..2d2f4e1 100644 --- a/DynamORM.Tests/Select/ParserTests.cs +++ b/DynamORM.Tests/Select/ParserTests.cs @@ -482,6 +482,20 @@ namespace DynamORM.Tests.Select Assert.AreEqual("SELECT \"dbo\".\"Users\".\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\"", cmd.CommandText()); } + /// + /// Tests select field with alias. + /// + [Test] + public void TestSelectFieldAlias3() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.u)) + .Select(u => u.UserName.As(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.Tests/Select/TypedAccessTests.cs b/DynamORM.Tests/Select/TypedAccessTests.cs index 333c74e..1fcfb1b 100644 --- a/DynamORM.Tests/Select/TypedAccessTests.cs +++ b/DynamORM.Tests/Select/TypedAccessTests.cs @@ -38,7 +38,7 @@ namespace DynamORM.Tests.Select /// Test typed ORM. /// Type to test. [TestFixture(typeof(users))] - public class TypedAccessTests : TestsBase + public class TypedAccessTests : TestsBase where T : class { /// Setup test parameters. [TestFixtureSetUp] @@ -97,6 +97,18 @@ namespace DynamORM.Tests.Select Assert.AreEqual(200, list.Count); } + /// Test load all rows into mapped list alternate way. + [Test] + public virtual void TestTypedGetAll3() + { + var list = GetTestBuilder() + .From(x => x(typeof(T)).As(x.t)) + .Execute() + .ToList(); + + Assert.AreEqual(200, list.Count); + } + /// Test unknown op. [Test] public virtual void TestTypedUnknownOperation() diff --git a/DynamORM/Builders/IDynamicSelectQueryBuilder.cs b/DynamORM/Builders/IDynamicSelectQueryBuilder.cs index a4935e8..b8194ba 100644 --- a/DynamORM/Builders/IDynamicSelectQueryBuilder.cs +++ b/DynamORM/Builders/IDynamicSelectQueryBuilder.cs @@ -5,12 +5,17 @@ namespace DynamORM.Builders { /// Dynamic select query builder interface. /// This interface it publically available. Implementation should be hidden. - public interface IDynamicSelectQueryBuilder : IDynamicQueryBuilder, IEnumerable + public interface IDynamicSelectQueryBuilder : IDynamicQueryBuilder ////, IEnumerable { /// Execute this builder. /// Enumerator of objects expanded from query. IEnumerable Execute(); + /// Execute this builder and map to given type. + /// Type of object to map on. + /// Enumerator of objects expanded from query. + IEnumerable Execute() where T : class; + /// Returns a single result. /// Result of a query. object Scalar(); diff --git a/DynamORM/DynamicExtensions.cs b/DynamORM/DynamicExtensions.cs index 5b61315..5487b65 100644 --- a/DynamORM/DynamicExtensions.cs +++ b/DynamORM/DynamicExtensions.cs @@ -913,7 +913,15 @@ namespace DynamORM int c = r.FieldCount; for (int i = 0; i < c; i++) - d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]); + try + { + d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]); + } + catch (ArgumentException argex) + { + throw new ArgumentException( + string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)), "Column name or alias", argex); + } return e; } diff --git a/DynamORM/DynamicTable.cs b/DynamORM/DynamicTable.cs index a11b05b..6ded5a4 100644 --- a/DynamORM/DynamicTable.cs +++ b/DynamORM/DynamicTable.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Data; using System.Dynamic; using System.Linq; +using System.Text; using DynamORM.Builders; using DynamORM.Builders.Extensions; using DynamORM.Builders.Implementation; @@ -340,14 +341,30 @@ namespace DynamORM { using (var con = Database.Open()) using (var cmd = con.CreateCommand()) - { - using (var rdr = cmd - .SetCommand(sql) - .AddParameters(Database, args) - .ExecuteReader()) - while (rdr.Read()) - yield return rdr.RowToDynamic(); - } + using (var rdr = cmd + .SetCommand(sql, args) + .ExecuteReader()) + while (rdr.Read()) + { + dynamic val = null; + + // Work around to avoid yield being in try...catch block: + // http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch + try + { + val = rdr.RowToDynamic(); + } + catch (ArgumentException argex) + { + var sb = new StringBuilder(); + cmd.Dump(sb); + + throw new ArgumentException(string.Format("{0}{1}{2}", argex.Message, Environment.NewLine, sb), + argex.InnerException.NullOr(a => a, argex)); + } + + yield return val; + } } /// Enumerate the reader and yield the result. @@ -357,13 +374,30 @@ namespace DynamORM { using (var con = Database.Open()) using (var cmd = con.CreateCommand()) - { - using (var rdr = cmd - .SetCommand(builder) - .ExecuteReader()) - while (rdr.Read()) - yield return rdr.RowToDynamic(); - } + using (var rdr = cmd + .SetCommand(builder) + .ExecuteReader()) + while (rdr.Read()) + { + dynamic val = null; + + // Work around to avoid yield being in try...catch block: + // http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch + try + { + val = rdr.RowToDynamic(); + } + catch (ArgumentException argex) + { + var sb = new StringBuilder(); + cmd.Dump(sb); + + throw new ArgumentException(string.Format("{0}{1}{2}", argex.Message, Environment.NewLine, sb), + argex.InnerException.NullOr(a => a, argex)); + } + + yield return val; + } } /// Create new .