This commit is contained in:
@@ -410,7 +410,10 @@ namespace DynamORM.Builders.Implementation
|
||||
|
||||
// If there are parameters to transform, but cannot store them, it is an error
|
||||
if (node.Parameters.Count != 0 && pars == null)
|
||||
throw new InvalidOperationException(string.Format("The parameters in this command '{0}' cannot be added to a null collection.", node.Parameters));
|
||||
return string.Format("({0})", str);
|
||||
|
||||
// TODO: Make special condiion
|
||||
//throw new InvalidOperationException(string.Format("The parameters in this command '{0}' cannot be added to a null collection.", node.Parameters));
|
||||
|
||||
// Copy parameters to new comand
|
||||
foreach (KeyValuePair<string, IParameter> parameter in node.Parameters)
|
||||
@@ -890,7 +893,7 @@ namespace DynamORM.Builders.Implementation
|
||||
ITableInfo tableInfo = !string.IsNullOrEmpty(tableName) ?
|
||||
Tables.FirstOrDefault(x => !string.IsNullOrEmpty(x.Alias) && x.Alias.ToLower() == tableName) ??
|
||||
Tables.FirstOrDefault(x => x.Name.ToLower() == tableName.ToLower()) ?? Tables.FirstOrDefault() :
|
||||
this is DynamicModifyBuilder ? Tables.FirstOrDefault() : null;
|
||||
this is DynamicModifyBuilder || Tables.Count == 1 ? Tables.FirstOrDefault() : null;
|
||||
|
||||
// Try to get column from schema
|
||||
if (tableInfo != null && tableInfo.Schema != null)
|
||||
|
||||
@@ -128,12 +128,16 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <returns>Enumerator of objects expanded from query.</returns>
|
||||
public virtual IEnumerable<dynamic> Execute()
|
||||
{
|
||||
DynamicCachedReader cache = null;
|
||||
using (IDbConnection con = Database.Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(this)
|
||||
.ExecuteReader())
|
||||
while (rdr.Read())
|
||||
{
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(this)
|
||||
.ExecuteReader())
|
||||
cache = new DynamicCachedReader(rdr);
|
||||
|
||||
while (cache.Read())
|
||||
{
|
||||
dynamic val = null;
|
||||
|
||||
@@ -141,7 +145,7 @@ namespace DynamORM.Builders.Implementation
|
||||
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
||||
try
|
||||
{
|
||||
val = rdr.RowToDynamic();
|
||||
val = cache.RowToDynamic();
|
||||
}
|
||||
catch (ArgumentException argex)
|
||||
{
|
||||
@@ -154,6 +158,7 @@ namespace DynamORM.Builders.Implementation
|
||||
|
||||
yield return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Execute this builder and map to given type.</summary>
|
||||
@@ -161,6 +166,7 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <returns>Enumerator of objects expanded from query.</returns>
|
||||
public virtual IEnumerable<T> Execute<T>() where T : class
|
||||
{
|
||||
DynamicCachedReader cache = null;
|
||||
DynamicTypeMap mapper = DynamicMapperCache.GetMapper<T>();
|
||||
|
||||
if (mapper == null)
|
||||
@@ -172,27 +178,29 @@ namespace DynamORM.Builders.Implementation
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(this)
|
||||
.ExecuteReader())
|
||||
while (rdr.Read())
|
||||
cache = new DynamicCachedReader(rdr);
|
||||
|
||||
while (cache.Read())
|
||||
{
|
||||
dynamic val = null;
|
||||
|
||||
// Work around to avoid yield being in try...catchblock:
|
||||
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
||||
try
|
||||
{
|
||||
dynamic val = null;
|
||||
|
||||
// Work around to avoid yield being in try...catchblock:
|
||||
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
||||
try
|
||||
{
|
||||
val = rdr.RowToDynamic();
|
||||
}
|
||||
catch (ArgumentException argex)
|
||||
{
|
||||
StringBuilder 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 mapper.Create(val) as T;
|
||||
val = cache.RowToDynamic();
|
||||
}
|
||||
catch (ArgumentException argex)
|
||||
{
|
||||
StringBuilder 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 mapper.Create(val) as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +216,23 @@ namespace DynamORM.Builders.Implementation
|
||||
reader(rdr);
|
||||
}
|
||||
|
||||
/// <summary>Execute this builder as a data reader, but
|
||||
/// first makes a full reader copy in memory.</summary>
|
||||
/// <param name="reader">Action containing reader.</param>
|
||||
public virtual void ExecuteCachedDataReader(Action<IDataReader> reader)
|
||||
{
|
||||
DynamicCachedReader cache = null;
|
||||
|
||||
using (IDbConnection con = Database.Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(this)
|
||||
.ExecuteReader())
|
||||
cache = new DynamicCachedReader(rdr);
|
||||
|
||||
reader(cache);
|
||||
}
|
||||
|
||||
/// <summary>Returns a single result.</summary>
|
||||
/// <returns>Result of a query.</returns>
|
||||
public virtual object Scalar()
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<Compile Include="Builders\IDynamicQueryBuilder.cs" />
|
||||
<Compile Include="Builders\IParameter.cs" />
|
||||
<Compile Include="Builders\ITableInfo.cs" />
|
||||
<Compile Include="DynamicCachedReader.cs" />
|
||||
<Compile Include="DynamicColumn.cs" />
|
||||
<Compile Include="DynamicCommand.cs" />
|
||||
<Compile Include="DynamicConnection.cs" />
|
||||
|
||||
@@ -170,6 +170,15 @@ namespace DynamORM
|
||||
/// <param name="options">Connection options. <see cref="DynamicDatabaseOptions.SingleConnection"/> required.</param>
|
||||
public DynamicDatabase(IDbConnection connection, DynamicDatabaseOptions options)
|
||||
{
|
||||
// Try to find correct provider if possible
|
||||
Type t = connection.GetType();
|
||||
if (t == typeof(System.Data.SqlClient.SqlConnection))
|
||||
_provider = System.Data.SqlClient.SqlClientFactory.Instance;
|
||||
else if (t == typeof(System.Data.Odbc.OdbcConnection))
|
||||
_provider = System.Data.Odbc.OdbcFactory.Instance;
|
||||
else if (t == typeof(System.Data.OleDb.OleDbConnection))
|
||||
_provider = System.Data.OleDb.OleDbFactory.Instance;
|
||||
|
||||
IsDisposed = false;
|
||||
InitCommon(connection.ConnectionString, options);
|
||||
TransactionPool.Add(connection, new Stack<IDbTransaction>());
|
||||
@@ -315,6 +324,15 @@ namespace DynamORM
|
||||
{
|
||||
return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <typeparam name="T">Type which can be represented in database.</typeparam>
|
||||
/// <param name="alias">Table alias.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder From<T>(string alias)
|
||||
{
|
||||
return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
@@ -1112,13 +1130,17 @@ namespace DynamORM
|
||||
/// <returns>Enumerator of objects expanded from query.</returns>
|
||||
public virtual IEnumerable<dynamic> Query(string sql, params object[] args)
|
||||
{
|
||||
DynamicCachedReader cache = null;
|
||||
using (IDbConnection con = Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(sql)
|
||||
.AddParameters(this, args)
|
||||
.ExecuteReader())
|
||||
while (rdr.Read())
|
||||
{
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(sql)
|
||||
.AddParameters(this, args)
|
||||
.ExecuteReader())
|
||||
cache = new DynamicCachedReader(rdr);
|
||||
|
||||
while (cache.Read())
|
||||
{
|
||||
dynamic val = null;
|
||||
|
||||
@@ -1126,7 +1148,7 @@ namespace DynamORM
|
||||
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
||||
try
|
||||
{
|
||||
val = rdr.RowToDynamic();
|
||||
val = cache.RowToDynamic();
|
||||
}
|
||||
catch (ArgumentException argex)
|
||||
{
|
||||
@@ -1139,6 +1161,7 @@ namespace DynamORM
|
||||
|
||||
yield return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Enumerate the reader and yield the result.</summary>
|
||||
@@ -1146,12 +1169,16 @@ namespace DynamORM
|
||||
/// <returns>Enumerator of objects expanded from query.</returns>
|
||||
public virtual IEnumerable<dynamic> Query(IDynamicQueryBuilder builder)
|
||||
{
|
||||
DynamicCachedReader cache = null;
|
||||
using (IDbConnection con = Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(builder)
|
||||
.ExecuteReader())
|
||||
while (rdr.Read())
|
||||
{
|
||||
using (IDataReader rdr = cmd
|
||||
.SetCommand(builder)
|
||||
.ExecuteReader())
|
||||
cache = new DynamicCachedReader(rdr);
|
||||
|
||||
while (cache.Read())
|
||||
{
|
||||
dynamic val = null;
|
||||
|
||||
@@ -1159,7 +1186,7 @@ namespace DynamORM
|
||||
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
||||
try
|
||||
{
|
||||
val = rdr.RowToDynamic();
|
||||
val = cache.RowToDynamic();
|
||||
}
|
||||
catch (ArgumentException argex)
|
||||
{
|
||||
@@ -1172,6 +1199,7 @@ namespace DynamORM
|
||||
|
||||
yield return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Query
|
||||
@@ -1321,8 +1349,12 @@ namespace DynamORM
|
||||
/// If your database doesn't get those values in upper case (like most of the databases) you should override this method.</returns>
|
||||
protected virtual IEnumerable<DynamicSchemaColumn> ReadSchema(IDbCommand cmd)
|
||||
{
|
||||
DataTable st = null;
|
||||
|
||||
using (IDataReader rdr = cmd.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo))
|
||||
using (DataTable st = rdr.GetSchemaTable())
|
||||
st = rdr.GetSchemaTable();
|
||||
|
||||
using (st)
|
||||
foreach (DataRow col in st.Rows)
|
||||
{
|
||||
dynamic c = col.RowToDynamicUpper();
|
||||
@@ -1330,7 +1362,7 @@ namespace DynamORM
|
||||
yield return new DynamicSchemaColumn
|
||||
{
|
||||
Name = c.COLUMNNAME,
|
||||
Type = DynamicExtensions.TypeMap.TryGetNullable((Type)c.DATATYPE) ?? DbType.String,
|
||||
Type = ReadSchemaType(c),
|
||||
IsKey = c.ISKEY ?? false,
|
||||
IsUnique = c.ISUNIQUE ?? false,
|
||||
Size = (int)(c.COLUMNSIZE ?? 0),
|
||||
@@ -1340,6 +1372,30 @@ namespace DynamORM
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reads the type of column from the schema.</summary>
|
||||
/// <param name="schema">The schema.</param>
|
||||
/// <returns>GEneric parameter type.</returns>
|
||||
protected virtual DbType ReadSchemaType(dynamic schema)
|
||||
{
|
||||
Type type = (Type)schema.DATATYPE;
|
||||
|
||||
// Small hack for SQL Server Provider
|
||||
if (type == typeof(string) && Provider != null && Provider.GetType() == typeof(System.Data.SqlClient.SqlClientFactory))
|
||||
{
|
||||
var map = (schema as IDictionary<string, object>);
|
||||
string typeName = (map.TryGetValue("DATATYPENAME") ?? string.Empty).ToString();
|
||||
|
||||
switch (typeName){
|
||||
case "varchar":
|
||||
return DbType.AnsiString;
|
||||
case "nvarchar":
|
||||
return DbType.String;
|
||||
}
|
||||
}
|
||||
|
||||
return DynamicExtensions.TypeMap.TryGetNullable(type) ?? DbType.String;
|
||||
}
|
||||
|
||||
private Dictionary<string, DynamicSchemaColumn> BuildAndCacheSchema(string tableName, DynamicTypeMap mapper, string owner = null)
|
||||
{
|
||||
Dictionary<string, DynamicSchemaColumn> schema = null;
|
||||
|
||||
@@ -286,6 +286,8 @@ namespace DynamORM
|
||||
|
||||
if (p.DbType == DbType.String)
|
||||
p.Size = item.ToString().Length > 4000 ? -1 : 4000;
|
||||
else if (p.DbType == DbType.AnsiString)
|
||||
p.Size = item.ToString().Length > 8000 ? -1 : 8000;
|
||||
}
|
||||
|
||||
cmd.Parameters.Add(p);
|
||||
@@ -328,7 +330,9 @@ namespace DynamORM
|
||||
{
|
||||
p.DbType = TypeMap.TryGetNullable(value.GetType()) ?? DbType.String;
|
||||
|
||||
if (p.DbType == DbType.String)
|
||||
if (p.DbType == DbType.AnsiString)
|
||||
p.Size = value.ToString().Length > 8000 ? -1 : 8000;
|
||||
else if (p.DbType == DbType.String)
|
||||
p.Size = value.ToString().Length > 4000 ? -1 : 4000;
|
||||
|
||||
p.Value = value;
|
||||
@@ -379,7 +383,9 @@ namespace DynamORM
|
||||
{
|
||||
p.DbType = TypeMap.TryGetNullable(item.Value.GetType()) ?? DbType.String;
|
||||
|
||||
if (p.DbType == DbType.String)
|
||||
if (p.DbType == DbType.AnsiString)
|
||||
p.Size = item.Value.ToString().Length > 8000 ? -1 : 8000;
|
||||
else if (p.DbType == DbType.String)
|
||||
p.Size = item.Value.ToString().Length > 4000 ? -1 : 4000;
|
||||
|
||||
p.Value = item.Value;
|
||||
@@ -516,7 +522,7 @@ namespace DynamORM
|
||||
param.Direction = parameterDirection;
|
||||
param.DbType = databaseType;
|
||||
param.Size = size;
|
||||
param.Value = value;
|
||||
param.Value = value ?? DBNull.Value;
|
||||
command.Parameters.Add(param);
|
||||
|
||||
return command;
|
||||
@@ -535,7 +541,7 @@ namespace DynamORM
|
||||
param.ParameterName = parameterName;
|
||||
param.DbType = databaseType;
|
||||
param.Size = size;
|
||||
param.Value = value;
|
||||
param.Value = value ?? DBNull.Value;
|
||||
command.Parameters.Add(param);
|
||||
|
||||
return command;
|
||||
@@ -552,7 +558,7 @@ namespace DynamORM
|
||||
IDbDataParameter param = command.CreateParameter();
|
||||
param.ParameterName = parameterName;
|
||||
param.DbType = databaseType;
|
||||
param.Value = value;
|
||||
param.Value = value ?? DBNull.Value;
|
||||
command.Parameters.Add(param);
|
||||
|
||||
return command;
|
||||
@@ -947,8 +953,14 @@ namespace DynamORM
|
||||
IDynamicSelectQueryBuilder sub = b.SubQuery();
|
||||
|
||||
subquery(b, sub);
|
||||
|
||||
(b as DynamicQueryBuilder).ParseCommand(sub as DynamicQueryBuilder, b.Parameters);
|
||||
try
|
||||
{
|
||||
(b as DynamicQueryBuilder).ParseCommand(sub as DynamicQueryBuilder, b.Parameters);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// This might occur if join was made to subquery
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
@@ -1343,6 +1355,9 @@ namespace DynamORM
|
||||
/// provided <see cref="System.Data.DbType"/>.</returns>
|
||||
public static Type ToType(this DbType dbt)
|
||||
{
|
||||
if (dbt == DbType.String)
|
||||
return typeof(string);
|
||||
|
||||
foreach (KeyValuePair<Type, DbType> tdbt in TypeMap)
|
||||
if (tdbt.Value == dbt)
|
||||
return tdbt.Key;
|
||||
@@ -1350,6 +1365,14 @@ namespace DynamORM
|
||||
return typeof(object);
|
||||
}
|
||||
|
||||
/// <summary>Determines whether the specified value is has only ASCII chars.</summary>
|
||||
/// <param name="value">The value to check.</param>
|
||||
/// <returns>Returns <c>true</c> if the specified value has only ASCII cars; otherwise, <c>false</c>.</returns>
|
||||
public static bool IsASCII(this string value)
|
||||
{
|
||||
return Encoding.UTF8.GetByteCount(value) == value.Length;
|
||||
}
|
||||
|
||||
#endregion Type extensions
|
||||
|
||||
#region IDictionary extensions
|
||||
@@ -1422,6 +1445,14 @@ namespace DynamORM
|
||||
yield return r.RowToDynamic();
|
||||
}
|
||||
|
||||
internal static IDataReader CachedReader(this IDataReader r)
|
||||
{
|
||||
if (r is DynamicCachedReader)
|
||||
return r;
|
||||
|
||||
return new DynamicCachedReader(r);
|
||||
}
|
||||
|
||||
#endregion IDataReader extensions
|
||||
|
||||
#region Mapper extensions
|
||||
|
||||
@@ -122,6 +122,7 @@ namespace DynamORM
|
||||
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) :
|
||||
@@ -158,13 +159,21 @@ namespace DynamORM
|
||||
mainResult = types[0].GetDefaultValue();
|
||||
|
||||
if (types[0] == typeof(IDataReader))
|
||||
mainResult = cmd.ExecuteReader();
|
||||
{
|
||||
using (IDataReader rdr = cmd.ExecuteReader())
|
||||
mainResult = rdr.CachedReader();
|
||||
}
|
||||
else if (types[0].IsGenericEnumerable())
|
||||
{
|
||||
Type argType = types[0].GetGenericArguments().First();
|
||||
if (argType == typeof(object))
|
||||
{
|
||||
IDataReader cache = null;
|
||||
using (IDataReader rdr = cmd.ExecuteReader())
|
||||
mainResult = rdr.EnumerateReader().ToList();
|
||||
cache = rdr.CachedReader();
|
||||
|
||||
mainResult = cache.EnumerateReader().ToList();
|
||||
}
|
||||
else if (argType.IsValueType)
|
||||
{
|
||||
Type listType = typeof(List<>).MakeGenericType(new Type[] { argType });
|
||||
@@ -172,9 +181,12 @@ namespace DynamORM
|
||||
|
||||
object defVal = listType.GetDefaultValue();
|
||||
|
||||
IDataReader cache = null;
|
||||
using (IDataReader rdr = cmd.ExecuteReader())
|
||||
while (rdr.Read())
|
||||
listInstance.Add(rdr[0] == DBNull.Value ? defVal : argType.CastObject(rdr[0]));
|
||||
cache = rdr.CachedReader();
|
||||
|
||||
while (cache.Read())
|
||||
listInstance.Add(cache[0] == DBNull.Value ? defVal : argType.CastObject(cache[0]));
|
||||
|
||||
mainResult = listInstance;
|
||||
}
|
||||
@@ -184,8 +196,11 @@ namespace DynamORM
|
||||
if (mapper == null)
|
||||
throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", argType.ToString()));
|
||||
|
||||
IDataReader cache = null;
|
||||
using (IDataReader rdr = cmd.ExecuteReader())
|
||||
mainResult = rdr.EnumerateReader().MapEnumerable(argType).ToList();
|
||||
cache = rdr.CachedReader();
|
||||
|
||||
mainResult = cache.EnumerateReader().MapEnumerable(argType).ToList();
|
||||
}
|
||||
}
|
||||
else if (types[0].IsValueType)
|
||||
|
||||
Reference in New Issue
Block a user