From ff966e5a052d21b03e645e33a4aa514ed1089e40 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 3 Nov 2015 09:49:17 +0000 Subject: [PATCH 1/2] Added Column attribute - to alias column names --- .../SqlMapperExtensionsAsync.cs | 55 +++++++-- Dapper.Contrib.Tests NET45/Program.cs | 2 +- Dapper.Contrib.Tests NET45/TestsAsync.cs | 16 +++ Dapper.Contrib.Tests/Program.cs | 4 +- Dapper.Contrib.Tests/Tests.cs | 18 ++- Dapper.Contrib/SqlMapperExtensions.cs | 104 +++++++++++++++--- 6 files changed, 169 insertions(+), 30 deletions(-) diff --git a/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs b/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs index 85b1e016b..33144d5cd 100644 --- a/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs +++ b/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs @@ -32,17 +32,35 @@ public static async Task GetAsync(this IDbConnection connection, dynamic i if (!GetQueries.TryGetValue(type.TypeHandle, out sql)) { var keys = KeyPropertiesCache(type); + var explicitKeys = ExplicitKeyPropertiesCache(type); if (keys.Count() > 1) throw new DataException("Get only supports an entity with a single [Key] property"); if (!keys.Any()) throw new DataException("Get only supports en entity with a [Key] property"); - var onlyKey = keys.First(); - + var key = keys.Any() ? keys.First() : explicitKeys.First(); var name = GetTableName(type); + ISqlAdapter adapter = GetFormatter(connection); + + var allProperties = TypePropertiesCache(type); + var computedProperties = ComputedPropertiesCache(type); + var allPropertiesExceptComputed = allProperties.Except(computedProperties).ToList(); + + var colsList = new StringBuilder(); + foreach (var prop in allPropertiesExceptComputed) + { + if (colsList.Length > 0) colsList.Append(", "); + adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); + colsList.Append(" as "); + adapter.AppendColumnName(colsList, prop.Name); + } + + var keyColumn = ColumnNamesCache(type, key.Name); + // TODO: query information schema and only select fields that are both in information schema and underlying class / interface - sql = "select * from " + name + " where " + onlyKey.Name + " = @id"; + sql = "select " + colsList.ToString() + " from " + name + " where " + keyColumn + " = @id"; + GetQueries[type.TypeHandle] = sql; } @@ -96,8 +114,19 @@ public static async Task> GetAllAsync(this IDbConnection conne var name = GetTableName(type); + ISqlAdapter adapter = GetFormatter(connection); + var props = TypePropertiesCache(type); + var colsList = new StringBuilder(); + foreach (var prop in props) + { + if (colsList.Length > 0) colsList.Append(", "); + adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); + colsList.Append(" as "); + adapter.AppendColumnName(colsList, prop.Name); + } + // TODO: query information schema and only select fields that are both in information schema and underlying class / interface - sql = "select * from " + name; + sql = "select " + colsList.ToString() + " from " + name; GetQueries[cacheType.TypeHandle] = sql; } @@ -149,10 +178,13 @@ public static async Task InsertAsync(this IDbConnection connection, T en var computedProperties = ComputedPropertiesCache(type); var allPropertiesExceptKeyAndComputed = allProperties.Except(keyProperties.Union(computedProperties)).ToList(); + var adapter = GetFormatter(connection); + for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count(); i++) { var property = allPropertiesExceptKeyAndComputed.ElementAt(i); - sbColumnList.AppendFormat("[{0}]", property.Name); + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnName(sbColumnList, column); if (i < allPropertiesExceptKeyAndComputed.Count() - 1) sbColumnList.Append(", "); } @@ -214,10 +246,13 @@ public static async Task UpdateAsync(this IDbConnection connection, T e var computedProperties = ComputedPropertiesCache(type); var nonIdProps = allProperties.Except(keyProperties.Union(computedProperties)).ToList(); + var adapter = GetFormatter(connection); + for (var i = 0; i < nonIdProps.Count(); i++) { var property = nonIdProps.ElementAt(i); - sb.AppendFormat("{0} = @{1}", property.Name, property.Name); + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnNameEqualsValue(sb, column, property.Name); if (i < nonIdProps.Count() - 1) sb.AppendFormat(", "); } @@ -225,7 +260,8 @@ public static async Task UpdateAsync(this IDbConnection connection, T e for (var i = 0; i < keyProperties.Count(); i++) { var property = keyProperties.ElementAt(i); - sb.AppendFormat("{0} = @{1}", property.Name, property.Name); + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnNameEqualsValue(sb, column, property.Name); if (i < keyProperties.Count() - 1) sb.AppendFormat(" and "); } @@ -261,10 +297,13 @@ public static async Task DeleteAsync(this IDbConnection connection, T e var sb = new StringBuilder(); sb.AppendFormat("delete from {0} where ", name); + var adapter = GetFormatter(connection); + for (var i = 0; i < keyProperties.Count(); i++) { var property = keyProperties.ElementAt(i); - sb.AppendFormat("{0} = @{1}", property.Name, property.Name); + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnNameEqualsValue(sb, column, property.Name); //fix for issue #336 if (i < keyProperties.Count() - 1) sb.AppendFormat(" and "); } diff --git a/Dapper.Contrib.Tests NET45/Program.cs b/Dapper.Contrib.Tests NET45/Program.cs index dab25254e..274492176 100644 --- a/Dapper.Contrib.Tests NET45/Program.cs +++ b/Dapper.Contrib.Tests NET45/Program.cs @@ -35,7 +35,7 @@ private static void Setup() connection.Execute(@" create table People (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) "); connection.Execute(@" create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null) "); connection.Execute(@" create table Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) "); - connection.Execute(@" create table Results (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, [Order] int not null) "); + connection.Execute(@" create table Results (ResultId int IDENTITY(1,1) not null, ResultName nvarchar(100) not null, [Order] int not null) "); connection.Execute(@" create table ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) "); connection.Execute(@" create table ObjectY (ObjectYId int not null, Name nvarchar(100) not null) "); } diff --git a/Dapper.Contrib.Tests NET45/TestsAsync.cs b/Dapper.Contrib.Tests NET45/TestsAsync.cs index 87fa30eab..eea7bf99d 100644 --- a/Dapper.Contrib.Tests NET45/TestsAsync.cs +++ b/Dapper.Contrib.Tests NET45/TestsAsync.cs @@ -89,6 +89,22 @@ public async Task TableNameAsync() } } + public async Task ColumnNameAsync() + { + using (var connection = GetOpenConnection()) + { + await connection.DeleteAllAsync(); + + // tests against "Name" column (set by Column attribute on Result.FullName ) + await connection.InsertAsync(new Result { Name = "Mike" }); + (await connection.GetAsync(1)).Name.IsEqualTo("Mike"); + (await connection.UpdateAsync(new Result() { Id = 1, Name = "Michael" })).IsEqualTo(true); + (await connection.GetAsync(1)).Name.IsEqualTo("Michael"); + (await connection.DeleteAsync(new Result() { Id = 1 })).IsEqualTo(true); + (await connection.GetAsync(1)).IsNull(); + } + } + public async Task TestSimpleGetAsync() { using (var connection = GetOpenConnection()) diff --git a/Dapper.Contrib.Tests/Program.cs b/Dapper.Contrib.Tests/Program.cs index 907cb2286..80c52a902 100644 --- a/Dapper.Contrib.Tests/Program.cs +++ b/Dapper.Contrib.Tests/Program.cs @@ -11,7 +11,7 @@ static void Main(string[] args) { Setup(); RunTests(); - Console.WriteLine("Press any key..."); + Console.WriteLine("Press any key..."); Console.ReadKey(); } @@ -32,7 +32,7 @@ private static void Setup() connection.Execute(@" create table People (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) "); connection.Execute(@" create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null) "); connection.Execute(@" create table Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) "); - connection.Execute(@" create table Results (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, [Order] int not null) "); + connection.Execute(@" create table Results (ResultId int IDENTITY(1,1) not null, ResultName nvarchar(100) not null, [Order] int not null) "); connection.Execute(@" create table ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) "); connection.Execute(@" create table ObjectY (ObjectYId int not null, Name nvarchar(100) not null) "); } diff --git a/Dapper.Contrib.Tests/Tests.cs b/Dapper.Contrib.Tests/Tests.cs index 908c64803..2b0ad119e 100644 --- a/Dapper.Contrib.Tests/Tests.cs +++ b/Dapper.Contrib.Tests/Tests.cs @@ -74,7 +74,9 @@ public class Car [Table("Results")] public class Result { + [Column("ResultId")] public int Id { get; set; } + [Column("ResultName")] public string Name { get; set; } public int Order { get; set; } } @@ -191,6 +193,20 @@ public void TableName() } } + public void ColumnName() + { + using (var connection = GetOpenConnection()) + { + // tests against "Name" column (set by Column attribute on Result.FullName ) + connection.Insert(new Result { Name = "Mike" }); + connection.Get(1).Name.IsEqualTo("Mike"); + connection.Update(new Result() { Id = 1, Name = "Michael" }).IsEqualTo(true); + connection.Get(1).Name.IsEqualTo("Michael"); + connection.Delete(new Result() { Id = 1 }).IsEqualTo(true); + connection.Get(1).IsNull(); + } + } + public void TestSimpleGet() { using (var connection = GetOpenConnection()) @@ -342,7 +358,7 @@ public void InsertWithCustomDbType() { sqliteCodeCalled = ex.Message.IndexOf("There was an error parsing the query", StringComparison.InvariantCultureIgnoreCase) >= 0; } -// ReSharper disable once EmptyGeneralCatchClause + // ReSharper disable once EmptyGeneralCatchClause catch (Exception) { } diff --git a/Dapper.Contrib/SqlMapperExtensions.cs b/Dapper.Contrib/SqlMapperExtensions.cs index e318bafa7..36d0a6a11 100644 --- a/Dapper.Contrib/SqlMapperExtensions.cs +++ b/Dapper.Contrib/SqlMapperExtensions.cs @@ -37,6 +37,7 @@ public interface ITableNameMapper private static readonly ConcurrentDictionary> ComputedProperties = new ConcurrentDictionary>(); private static readonly ConcurrentDictionary GetQueries = new ConcurrentDictionary(); private static readonly ConcurrentDictionary TypeTableName = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary> ColumnNames = new ConcurrentDictionary>(); private static readonly Dictionary AdapterDictionary = new Dictionary { {"sqlconnection", new SqlServerAdapter()}, @@ -112,6 +113,31 @@ private static List TypePropertiesCache(Type type) return properties.ToList(); } + private static string ColumnNamesCache(Type type, string propertyname) + { + ConcurrentDictionary pis; + if (ColumnNames.TryGetValue(type.TypeHandle, out pis)) + { + if (pis.ContainsKey(propertyname)) + return pis[propertyname]; + + return propertyname; + } + + var columnNames = type.GetProperties() + .Where(p => p.GetCustomAttributes(typeof(ColumnAttribute), false).Any()) + .ToDictionary(p => p.Name, + p =>((ColumnAttribute) p.GetCustomAttributes(typeof(ColumnAttribute), false).First()).Name); + + var columnNamesConc = new ConcurrentDictionary(columnNames); + ColumnNames[type.TypeHandle] = columnNamesConc; + + if (columnNamesConc.ContainsKey(propertyname)) + return columnNamesConc[propertyname]; + + return propertyname; + } + private static bool IsWriteable(PropertyInfo pi) { var attributes = pi.GetCustomAttributes(typeof(WriteAttribute), false); @@ -149,8 +175,25 @@ public static T Get(this IDbConnection connection, dynamic id, IDbTransaction var name = GetTableName(type); + ISqlAdapter adapter = GetFormatter(connection); + + var allProperties = TypePropertiesCache(type); + var computedProperties = ComputedPropertiesCache(type); + var allPropertiesExceptComputed = allProperties.Except(computedProperties).ToList(); + + var colsList = new StringBuilder(); + foreach (var prop in allPropertiesExceptComputed) + { + if (colsList.Length > 0) colsList.Append(", "); + adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); + colsList.Append(" as "); + adapter.AppendColumnName(colsList, prop.Name); + } + + var keyColumn = ColumnNamesCache(type, key.Name); + // TODO: query information schema and only select fields that are both in information schema and underlying class / interface - sql = "select * from " + name + " where " + key.Name + " = @id"; + sql = "select " + colsList.ToString() + " from " + name + " where " + keyColumn + " = @id"; GetQueries[type.TypeHandle] = sql; } @@ -208,8 +251,19 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac var name = GetTableName(type); - // TODO: query information schema and only select fields that are both in information schema and underlying class / interface - sql = "select * from " + name; + ISqlAdapter adapter = GetFormatter(connection); + var props = TypePropertiesCache(type); + var colsList = new StringBuilder(); + foreach (var prop in props) + { + if (colsList.Length > 0) colsList.Append(", "); + adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); + colsList.Append(" as "); + adapter.AppendColumnName(colsList, prop.Name); + } + + sql = "select " + colsList.ToString() + " from " + name; + GetQueries[cacheType.TypeHandle] = sql; } @@ -295,7 +349,8 @@ public static long Insert(this IDbConnection connection, T entityToInsert, ID for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count(); i++) { var property = allPropertiesExceptKeyAndComputed.ElementAt(i); - adapter.AppendColumnName(sbColumnList, property.Name); //fix for issue #336 + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnName(sbColumnList, column); //fix for issue #336 if (i < allPropertiesExceptKeyAndComputed.Count() - 1) sbColumnList.Append(", "); } @@ -368,7 +423,8 @@ public static bool Update(this IDbConnection connection, T entityToUpdate, ID for (var i = 0; i < nonIdProps.Count(); i++) { var property = nonIdProps.ElementAt(i); - adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336 + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnNameEqualsValue(sb, column, property.Name); //fix for issue #336 if (i < nonIdProps.Count() - 1) sb.AppendFormat(", "); } @@ -376,7 +432,8 @@ public static bool Update(this IDbConnection connection, T entityToUpdate, ID for (var i = 0; i < keyProperties.Count(); i++) { var property = keyProperties.ElementAt(i); - adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336 + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnNameEqualsValue(sb, column, property.Name); //fix for issue #336 if (i < keyProperties.Count() - 1) sb.AppendFormat(" and "); } @@ -417,7 +474,8 @@ public static bool Delete(this IDbConnection connection, T entityToDelete, ID for (var i = 0; i < keyProperties.Count(); i++) { var property = keyProperties.ElementAt(i); - adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336 + var column = ColumnNamesCache(type, property.Name); + adapter.AppendColumnNameEqualsValue(sb, column, property.Name); //fix for issue #336 if (i < keyProperties.Count() - 1) sb.AppendFormat(" and "); } @@ -629,6 +687,16 @@ public TableAttribute(string tableName) public string Name { get; set; } } + [AttributeUsage(AttributeTargets.Property)] + public class ColumnAttribute : Attribute + { + public ColumnAttribute(string columnName) + { + Name = columnName; + } + public string Name { get; private set; } + } + // do not want to depend on data annotations that is not in client profile [AttributeUsage(AttributeTargets.Property)] public class KeyAttribute : Attribute @@ -662,7 +730,7 @@ public partial interface ISqlAdapter //new methods for issue #336 void AppendColumnName(StringBuilder sb, string columnName); - void AppendColumnNameEqualsValue(StringBuilder sb, string columnName); + void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName); } public partial class SqlServerAdapter : ISqlAdapter @@ -690,9 +758,9 @@ public void AppendColumnName(StringBuilder sb, string columnName) sb.AppendFormat("[{0}]", columnName); } - public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName) { - sb.AppendFormat("[{0}] = @{1}", columnName, columnName); + sb.AppendFormat("[{0}] = @{1}", columnName, propertyName); } } @@ -721,9 +789,9 @@ public void AppendColumnName(StringBuilder sb, string columnName) sb.AppendFormat("[{0}]", columnName); } - public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName) { - sb.AppendFormat("[{0}] = @{1}", columnName, columnName); + sb.AppendFormat("[{0}] = @{1}", columnName, propertyName); } } @@ -751,9 +819,9 @@ public void AppendColumnName(StringBuilder sb, string columnName) sb.AppendFormat("`{0}`", columnName); } - public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName) { - sb.AppendFormat("`{0}` = @{1}", columnName, columnName); + sb.AppendFormat("`{0}` = @{1}", columnName, propertyName); } } @@ -801,9 +869,9 @@ public void AppendColumnName(StringBuilder sb, string columnName) sb.AppendFormat("\"{0}\"", columnName); } - public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName) { - sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName); + sb.AppendFormat("\"{0}\" = @{1}", columnName, propertyName); } } @@ -829,8 +897,8 @@ public void AppendColumnName(StringBuilder sb, string columnName) sb.AppendFormat("\"{0}\"", columnName); } - public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName) { - sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName); + sb.AppendFormat("\"{0}\" = @{1}", columnName, propertyName); } } From fd291bf6f19058e827b40ecdb612c7b2d7e3ced9 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 5 Nov 2015 17:25:54 +0000 Subject: [PATCH 2/2] Changes to PR#376 - suggestions from code review --- .../SqlMapperExtensionsAsync.cs | 18 +------- Dapper.Contrib/SqlMapperExtensions.cs | 45 ++++++++++--------- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs b/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs index 33144d5cd..c2052a1e5 100644 --- a/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs +++ b/Dapper.Contrib NET45/SqlMapperExtensionsAsync.cs @@ -40,26 +40,12 @@ public static async Task GetAsync(this IDbConnection connection, dynamic i var key = keys.Any() ? keys.First() : explicitKeys.First(); var name = GetTableName(type); - - ISqlAdapter adapter = GetFormatter(connection); - - var allProperties = TypePropertiesCache(type); - var computedProperties = ComputedPropertiesCache(type); - var allPropertiesExceptComputed = allProperties.Except(computedProperties).ToList(); - - var colsList = new StringBuilder(); - foreach (var prop in allPropertiesExceptComputed) - { - if (colsList.Length > 0) colsList.Append(", "); - adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); - colsList.Append(" as "); - adapter.AppendColumnName(colsList, prop.Name); - } + var colsList = ColumnListForSelect(connection, type); var keyColumn = ColumnNamesCache(type, key.Name); // TODO: query information schema and only select fields that are both in information schema and underlying class / interface - sql = "select " + colsList.ToString() + " from " + name + " where " + keyColumn + " = @id"; + sql = "select " + colsList + " from " + name + " where " + keyColumn + " = @id"; GetQueries[type.TypeHandle] = sql; } diff --git a/Dapper.Contrib/SqlMapperExtensions.cs b/Dapper.Contrib/SqlMapperExtensions.cs index 36d0a6a11..9a0be6bae 100644 --- a/Dapper.Contrib/SqlMapperExtensions.cs +++ b/Dapper.Contrib/SqlMapperExtensions.cs @@ -124,10 +124,10 @@ private static string ColumnNamesCache(Type type, string propertyname) return propertyname; } - var columnNames = type.GetProperties() - .Where(p => p.GetCustomAttributes(typeof(ColumnAttribute), false).Any()) + var columnNames = TypePropertiesCache(type) + .Where(p => p.GetCustomAttributes(false).Any(attr => attr.GetType().Name == "ColumnAttribute")) .ToDictionary(p => p.Name, - p =>((ColumnAttribute) p.GetCustomAttributes(typeof(ColumnAttribute), false).First()).Name); + p =>(p.GetCustomAttributes(typeof(ColumnAttribute), false).First() as dynamic).Name as string); var columnNamesConc = new ConcurrentDictionary(columnNames); ColumnNames[type.TypeHandle] = columnNamesConc; @@ -147,6 +147,26 @@ private static bool IsWriteable(PropertyInfo pi) return writeAttribute.Write; } + private static string ColumnListForSelect(IDbConnection connection, Type type) + { + ISqlAdapter adapter = GetFormatter(connection); + + var allProperties = TypePropertiesCache(type); + var computedProperties = ComputedPropertiesCache(type); + var allPropertiesExceptComputed = allProperties.Except(computedProperties).ToList(); + + var colsList = new StringBuilder(); + foreach (var prop in allPropertiesExceptComputed) + { + if (colsList.Length > 0) colsList.Append(", "); + adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); + colsList.Append(" as "); + adapter.AppendColumnName(colsList, prop.Name); + } + + return colsList.ToString(); + } + /// /// Returns a single entity by a single id from table "Ts". /// Id must be marked with [Key] attribute. @@ -174,26 +194,11 @@ public static T Get(this IDbConnection connection, dynamic id, IDbTransaction var key = keys.Any() ? keys.First() : explicitKeys.First(); var name = GetTableName(type); - - ISqlAdapter adapter = GetFormatter(connection); - - var allProperties = TypePropertiesCache(type); - var computedProperties = ComputedPropertiesCache(type); - var allPropertiesExceptComputed = allProperties.Except(computedProperties).ToList(); - - var colsList = new StringBuilder(); - foreach (var prop in allPropertiesExceptComputed) - { - if (colsList.Length > 0) colsList.Append(", "); - adapter.AppendColumnName(colsList, ColumnNamesCache(type, prop.Name)); - colsList.Append(" as "); - adapter.AppendColumnName(colsList, prop.Name); - } - + var colsList = ColumnListForSelect(connection, type); var keyColumn = ColumnNamesCache(type, key.Name); // TODO: query information schema and only select fields that are both in information schema and underlying class / interface - sql = "select " + colsList.ToString() + " from " + name + " where " + keyColumn + " = @id"; + sql = "select " + colsList + " from " + name + " where " + keyColumn + " = @id"; GetQueries[type.TypeHandle] = sql; }