Merge pull request #1387 from umbraco/temp-u4-8729

u4 8729
This commit is contained in:
Stephan
2016-07-19 12:07:41 +02:00
committed by GitHub
3 changed files with 93 additions and 79 deletions

View File

@@ -1,10 +1,10 @@
/* PetaPoco v4.0.3 - A Tiny ORMish thing for your POCO's.
* Copyright © 2011 Topten Software. All Rights Reserved.
*
*
* Apache License 2.0 - http://www.toptensoftware.com/petapoco/license
*
* Special thanks to Rob Conery (@robconery) for original inspiration (ie:Massive) and for
* use of Subsonic's T4 templates, Rob Sullivan (@DataChomp) for hard core DBA advice
*
* Special thanks to Rob Conery (@robconery) for original inspiration (ie:Massive) and for
* use of Subsonic's T4 templates, Rob Sullivan (@DataChomp) for hard core DBA advice
* and Adam Schroder (@schotime) for lots of suggestions, improvements and Oracle support
*/
@@ -88,7 +88,7 @@ namespace Umbraco.Core.Persistence
}
// Results from paged request
public class Page<T>
public class Page<T>
{
public long CurrentPage { get; set; }
public long TotalPages { get; set; }
@@ -202,7 +202,7 @@ namespace Umbraco.Core.Persistence
if (_providerName != null)
_factory = DbProviderFactories.GetFactory(_providerName);
string dbtype = (_factory == null ? _sharedConnection.GetType() : _factory.GetType()).Name;
if (dbtype.StartsWith("MySql")) _dbType = DBType.MySql;
@@ -385,7 +385,7 @@ namespace Umbraco.Core.Persistence
return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED";
}
}
// Helper to handle named parameters from object properties
static Regex rxParams = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
public static string ProcessParams(string _sql, object[] args_src, List<object> args_dest)
@@ -425,8 +425,8 @@ namespace Umbraco.Core.Persistence
}
// Expand collections to parameter lists
if ((arg_val as System.Collections.IEnumerable) != null &&
(arg_val as string) == null &&
if ((arg_val as System.Collections.IEnumerable) != null &&
(arg_val as string) == null &&
(arg_val as byte[]) == null)
{
var sb = new StringBuilder();
@@ -487,10 +487,10 @@ namespace Umbraco.Core.Persistence
}
else if (t == typeof(string))
{
// out of memory exception occurs if trying to save more than 4000 characters to SQL Server CE NText column.
// out of memory exception occurs if trying to save more than 4000 characters to SQL Server CE NText column.
//Set before attempting to set Size, or Size will always max out at 4000
if ((item as string).Length + 1 > 4000 && p.GetType().Name == "SqlCeParameter")
p.GetType().GetProperty("SqlDbType").SetValue(p, SqlDbType.NText, null);
p.GetType().GetProperty("SqlDbType").SetValue(p, SqlDbType.NText, null);
p.Size = (item as string).Length + 1;
if(p.Size < 4000)
@@ -676,12 +676,12 @@ namespace Umbraco.Core.Persistence
public bool ForceDateTimesToUtc { get; set; }
// Return a typed list of pocos
public List<T> Fetch<T>(string sql, params object[] args)
public List<T> Fetch<T>(string sql, params object[] args)
{
return Query<T>(sql, args).ToList();
}
public List<T> Fetch<T>(Sql sql)
public List<T> Fetch<T>(Sql sql)
{
return Fetch<T>(sql.SQL, sql.Arguments);
}
@@ -726,7 +726,7 @@ namespace Umbraco.Core.Persistence
return true;
}
public void BuildPageQueries<T>(long skip, long take, string sql, ref object[] args, out string sqlCount, out string sqlPage)
public void BuildPageQueries<T>(long skip, long take, string sql, ref object[] args, out string sqlCount, out string sqlPage)
{
// Add auto select clause
if (EnableAutoSelect)
@@ -764,8 +764,8 @@ namespace Umbraco.Core.Persistence
}
// Fetch a page
public Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args)
// Fetch a page
public Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args)
{
string sqlCount, sqlPage;
BuildPageQueries<T>((page-1)*itemsPerPage, itemsPerPage, sql, ref args, out sqlCount, out sqlPage);
@@ -791,7 +791,7 @@ namespace Umbraco.Core.Persistence
return result;
}
public Page<T> Page<T>(long page, long itemsPerPage, Sql sql)
public Page<T> Page<T>(long page, long itemsPerPage, Sql sql)
{
return Page<T>(page, itemsPerPage, sql.SQL, sql.Arguments);
}
@@ -820,7 +820,7 @@ namespace Umbraco.Core.Persistence
}
// Return an enumerable collection of pocos
public IEnumerable<T> Query<T>(string sql, params object[] args)
public IEnumerable<T> Query<T>(string sql, params object[] args)
{
if (EnableAutoSelect)
sql = AddSelectClause<T>(sql);
@@ -1033,7 +1033,7 @@ namespace Umbraco.Core.Persistence
}
private List<Delegate> Delegates { get; set; }
private Delegate GetItem(int index) { return Delegates[index]; }
/// <summary>
/// Calls the delegate at the specified index and returns its values
/// </summary>
@@ -1068,7 +1068,7 @@ namespace Umbraco.Core.Persistence
// Create a multi-poco factory
Func<IDataReader, Delegate, TRet> CreateMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
{
{
// Call each delegate
var dels = new List<Delegate>();
int pos = 0;
@@ -1088,7 +1088,7 @@ namespace Umbraco.Core.Persistence
static Dictionary<string, Delegate> AutoMappers = new Dictionary<string, Delegate>();
static System.Threading.ReaderWriterLockSlim RWLock = new System.Threading.ReaderWriterLockSlim();
// Get (or create) the multi-poco factory for a query
// Get (or create) the multi-poco factory for a query
Func<IDataReader, Delegate, TRet> GetMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
{
// Build a key string (this is crap, should address this at some point)
@@ -1113,8 +1113,8 @@ namespace Umbraco.Core.Persistence
if (MultiPocoFactories.TryGetValue(key, out oFactory))
{
//mpFactory = oFactory;
return (Func<IDataReader, Delegate, TRet>)oFactory;
}
return (Func<IDataReader, Delegate, TRet>)oFactory;
}
}
finally
{
@@ -1130,9 +1130,9 @@ namespace Umbraco.Core.Persistence
if (MultiPocoFactories.TryGetValue(key, out oFactory))
{
return (Func<IDataReader, Delegate, TRet>)oFactory;
}
// Create the factory
}
// Create the factory
var factory = CreateMultiPocoFactory<TRet>(types, sql, r);
MultiPocoFactories.Add(key, factory);
@@ -1207,54 +1207,54 @@ namespace Umbraco.Core.Persistence
}
}
public IEnumerable<T> Query<T>(Sql sql)
public IEnumerable<T> Query<T>(Sql sql)
{
return Query<T>(sql.SQL, sql.Arguments);
}
public bool Exists<T>(object primaryKey)
public bool Exists<T>(object primaryKey)
{
return FirstOrDefault<T>(string.Format("WHERE {0}=@0", EscapeSqlIdentifier(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey)), primaryKey) != null;
}
public T Single<T>(object primaryKey)
public T Single<T>(object primaryKey)
{
return Single<T>(string.Format("WHERE {0}=@0", EscapeSqlIdentifier(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey)), primaryKey);
}
public T SingleOrDefault<T>(object primaryKey)
public T SingleOrDefault<T>(object primaryKey)
{
return SingleOrDefault<T>(string.Format("WHERE {0}=@0", EscapeSqlIdentifier(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey)), primaryKey);
}
public T Single<T>(string sql, params object[] args)
public T Single<T>(string sql, params object[] args)
{
return Query<T>(sql, args).Single();
}
public T SingleOrDefault<T>(string sql, params object[] args)
public T SingleOrDefault<T>(string sql, params object[] args)
{
return Query<T>(sql, args).SingleOrDefault();
}
public T First<T>(string sql, params object[] args)
public T First<T>(string sql, params object[] args)
{
return Query<T>(sql, args).First();
}
public T FirstOrDefault<T>(string sql, params object[] args)
public T FirstOrDefault<T>(string sql, params object[] args)
{
return Query<T>(sql, args).FirstOrDefault();
}
public T Single<T>(Sql sql)
public T Single<T>(Sql sql)
{
return Query<T>(sql).Single();
}
public T SingleOrDefault<T>(Sql sql)
public T SingleOrDefault<T>(Sql sql)
{
return Query<T>(sql).SingleOrDefault();
}
public T First<T>(Sql sql)
public T First<T>(Sql sql)
{
return Query<T>(sql).First();
}
public T FirstOrDefault<T>(Sql sql)
public T FirstOrDefault<T>(Sql sql)
{
return Query<T>(sql).FirstOrDefault();
}
@@ -1285,7 +1285,7 @@ namespace Umbraco.Core.Persistence
return Insert(tableName, primaryKeyName, true, poco);
}
// Insert a poco into a table. If the poco has a property with the same name
// Insert a poco into a table. If the poco has a property with the same name
// as the primary key the id of the new record is assigned to it. Either way,
// the new id is returned.
public object Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco)
@@ -1721,7 +1721,7 @@ namespace Umbraco.Core.Persistence
{
cmd.CommandTimeout = CommandTimeout;
}
// Call hook
OnExecutingCommand(cmd);
@@ -1779,8 +1779,8 @@ namespace Umbraco.Core.Persistence
public class ExpandoColumn : PocoColumn
{
public override void SetValue(object target, object val) { (target as IDictionary<string, object>)[ColumnName]=val; }
public override object GetValue(object target)
{
public override object GetValue(object target)
{
object val=null;
(target as IDictionary<string, object>).TryGetValue(ColumnName, out val);
return val;
@@ -1803,7 +1803,7 @@ namespace Umbraco.Core.Persistence
}
static readonly ObjectCache ObjectCache = new MemoryCache("NPoco");
}
public class PocoData
@@ -1812,7 +1812,7 @@ namespace Umbraco.Core.Persistence
internal static bool UseLongKeys = false;
//USE ONLY FOR TESTING - default is one hr
internal static int SlidingExpirationSeconds = 3600;
public static PocoData ForObject(object o, string primaryKeyName)
{
var t = o.GetType();
@@ -1836,7 +1836,7 @@ namespace Umbraco.Core.Persistence
#endif
return ForType(t);
}
public static PocoData ForType(Type t)
{
#if !PETAPOCO_NO_DYNAMIC
@@ -1856,7 +1856,7 @@ namespace Umbraco.Core.Persistence
InnerLock.ExitReadLock();
}
// Cache it
InnerLock.EnterWriteLock();
try
@@ -1959,7 +1959,7 @@ namespace Umbraco.Core.Persistence
public Delegate GetFactory(string sql, string connString, bool ForceDateTimesToUtc, int firstColumn, int countColumns, IDataReader r)
{
//TODO: It would be nice to remove the irrelevant SQL parts - for a mapping operation anything after the SELECT clause isn't required.
//TODO: It would be nice to remove the irrelevant SQL parts - for a mapping operation anything after the SELECT clause isn't required.
// This would ensure less duplicate entries that get cached, currently both of these queries would be cached even though they are
// returning the same structured data:
// SELECT * FROM MyTable ORDER BY MyColumn
@@ -1981,7 +1981,7 @@ namespace Umbraco.Core.Persistence
combiner.AddInt(countColumns);
key = combiner.GetCombinedHashCode();
}
var objectCache = _managedCache.GetCache();
@@ -2029,7 +2029,7 @@ namespace Umbraco.Core.Persistence
il.Emit(OpCodes.Brfalse_S, lblNotNull); // obj, obj, fieldname, converter?, value
il.Emit(OpCodes.Pop); // obj, obj, fieldname, converter?
if (converter != null)
il.Emit(OpCodes.Pop); // obj, obj, fieldname,
il.Emit(OpCodes.Pop); // obj, obj, fieldname,
il.Emit(OpCodes.Ldnull); // obj, obj, fieldname, null
if (converter != null)
{
@@ -2169,7 +2169,7 @@ namespace Umbraco.Core.Persistence
// return it
var del = m.CreateDelegate(Expression.GetFuncType(typeof(IDataReader), type));
return del;
};
@@ -2178,7 +2178,7 @@ namespace Umbraco.Core.Persistence
// the line belows returns existing item or adds the new value if it doesn't exist
var value = (Lazy<Delegate>)objectCache.AddOrGetExisting(key, newValue, new CacheItemPolicy
{
//sliding expiration of 1 hr, if the same key isn't used in this
//sliding expiration of 1 hr, if the same key isn't used in this
// timeframe it will be removed from the cache
SlidingExpiration = new TimeSpan(0, 0, SlidingExpirationSeconds)
});
@@ -2272,7 +2272,7 @@ namespace Umbraco.Core.Persistence
public TableInfo TableInfo { get; private set; }
public Dictionary<string, PocoColumn> Columns { get; private set; }
static System.Threading.ReaderWriterLockSlim InnerLock = new System.Threading.ReaderWriterLockSlim();
/// <summary>
/// Returns a report of the current cache being utilized by PetaPoco
/// </summary>
@@ -2286,7 +2286,7 @@ namespace Umbraco.Core.Persistence
foreach (var pocoData in m_PocoDatas)
{
sb.AppendFormat("\t{0}\n", pocoData.Key);
sb.AppendFormat("\t\tTable:{0} - Col count:{1}\n", pocoData.Value.TableInfo.TableName, pocoData.Value.QueryColumns.Length);
sb.AppendFormat("\t\tTable:{0} - Col count:{1}\n", pocoData.Value.TableInfo.TableName, pocoData.Value.QueryColumns.Length);
}
var cache = managedCache.GetCache();
@@ -2299,7 +2299,7 @@ namespace Umbraco.Core.Persistence
totalBytes = Encoding.Unicode.GetByteCount(keys);
sb.AppendFormat("\tTotal byte for keys:{0}\n", totalBytes);
sb.AppendLine("\tAll Poco cache items:");
foreach (var item in cache)
@@ -2417,6 +2417,7 @@ namespace Umbraco.Core.Persistence
else
_rhs = sql;
_sqlFinal = null;
return this;
}

View File

@@ -22,8 +22,7 @@ namespace Umbraco.Core.Persistence
public static Sql From<T>(this Sql sql, ISqlSyntaxProvider sqlSyntax)
{
var type = typeof(T);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
return sql.From(sqlSyntax.GetQuotedTableName(tableName));
}
@@ -51,11 +50,10 @@ namespace Umbraco.Core.Persistence
public static Sql OrderBy<TColumn>(this Sql sql, Expression<Func<TColumn, object>> columnMember, ISqlSyntaxProvider sqlSyntax)
{
var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo;
var columnName = column.FirstAttribute<ColumnAttribute>().Name;
var columnName = column.GetColumnName();
var type = typeof(TColumn);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
//need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177
var syntax = string.Format("({0}.{1})",
@@ -74,11 +72,10 @@ namespace Umbraco.Core.Persistence
public static Sql OrderByDescending<TColumn>(this Sql sql, Expression<Func<TColumn, object>> columnMember, ISqlSyntaxProvider sqlSyntax)
{
var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo;
var columnName = column.FirstAttribute<ColumnAttribute>().Name;
var columnName = column.GetColumnName();
var type = typeof(TColumn);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
var syntax = string.Format("{0}.{1} DESC",
sqlSyntax.GetQuotedTableName(tableName),
@@ -96,7 +93,7 @@ namespace Umbraco.Core.Persistence
public static Sql GroupBy<TColumn>(this Sql sql, Expression<Func<TColumn, object>> columnMember, ISqlSyntaxProvider sqlProvider)
{
var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo;
var columnName = column.FirstAttribute<ColumnAttribute>().Name;
var columnName = column.GetColumnName();
return sql.GroupBy(sqlProvider.GetQuotedColumnName(columnName));
}
@@ -110,8 +107,7 @@ namespace Umbraco.Core.Persistence
public static Sql.SqlJoinClause InnerJoin<T>(this Sql sql, ISqlSyntaxProvider sqlSyntax)
{
var type = typeof(T);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
return sql.InnerJoin(sqlSyntax.GetQuotedTableName(tableName));
}
@@ -125,8 +121,7 @@ namespace Umbraco.Core.Persistence
public static Sql.SqlJoinClause LeftJoin<T>(this Sql sql, ISqlSyntaxProvider sqlSyntax)
{
var type = typeof(T);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
return sql.LeftJoin(sqlSyntax.GetQuotedTableName(tableName));
}
@@ -140,8 +135,7 @@ namespace Umbraco.Core.Persistence
public static Sql.SqlJoinClause LeftOuterJoin<T>(this Sql sql, ISqlSyntaxProvider sqlSyntax)
{
var type = typeof(T);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
return sql.LeftOuterJoin(sqlSyntax.GetQuotedTableName(tableName));
}
@@ -155,8 +149,7 @@ namespace Umbraco.Core.Persistence
public static Sql.SqlJoinClause RightJoin<T>(this Sql sql, ISqlSyntaxProvider sqlSyntax)
{
var type = typeof(T);
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var tableName = type.GetTableName();
return sql.RightJoin(sqlSyntax.GetQuotedTableName(tableName));
}
@@ -173,13 +166,14 @@ namespace Umbraco.Core.Persistence
{
var leftType = typeof(TLeft);
var rightType = typeof(TRight);
var leftTableName = leftType.FirstAttribute<TableNameAttribute>().Value;
var rightTableName = rightType.FirstAttribute<TableNameAttribute>().Value;
var leftTableName = leftType.GetTableName();
var rightTableName = rightType.GetTableName();
var left = ExpressionHelper.FindProperty(leftMember) as PropertyInfo;
var right = ExpressionHelper.FindProperty(rightMember) as PropertyInfo;
var leftColumnName = left.FirstAttribute<ColumnAttribute>().Name;
var rightColumnName = right.FirstAttribute<ColumnAttribute>().Name;
var leftColumn = ExpressionHelper.FindProperty(leftMember) as PropertyInfo;
var rightColumn = ExpressionHelper.FindProperty(rightMember) as PropertyInfo;
var leftColumnName = leftColumn.GetColumnName();
var rightColumnName = rightColumn.GetColumnName();
string onClause = string.Format("{0}.{1} = {2}.{3}",
sqlSyntax.GetQuotedTableName(leftTableName),
@@ -193,5 +187,20 @@ namespace Umbraco.Core.Persistence
{
return sql.Append(new Sql("ORDER BY " + String.Join(", ", (from x in columns select x + " DESC").ToArray())));
}
private static string GetTableName(this Type type)
{
// todo: returning string.Empty for now
// BUT the code bits that calls this method cannot deal with string.Empty so we
// should either throw, or fix these code bits...
var attr = type.FirstAttribute<TableNameAttribute>();
return attr == null || string.IsNullOrWhiteSpace(attr.Value) ? string.Empty : attr.Value;
}
private static string GetColumnName(this PropertyInfo column)
{
var attr = column.FirstAttribute<ColumnAttribute>();
return attr == null || string.IsNullOrWhiteSpace(attr.Name) ? column.Name : attr.Name;
}
}
}

View File

@@ -29,7 +29,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public override string GetQuotedTableName(string tableName)
{
return string.Format("[{0}]", tableName);
if (tableName.Contains(".") == false)
return string.Format("[{0}]", tableName);
var tableNameParts = tableName.Split(new[] { '.' }, 2);
return string.Format("[{0}].[{1}]", tableNameParts[0], tableNameParts[1]);
}
public override string GetQuotedColumnName(string columnName)