@@ -1,4 +1,4 @@
/* PetaPoco v4.0.2 - A Tiny ORMish thing for your POCO's.
/* 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
@@ -13,18 +13,16 @@
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Configuration ;
using System.Data ;
using System.Data.Common ;
using System.Diagnostics ;
using System.Linq ;
using System.Linq.Expressions ;
using System.Text ;
using System.Configuration ;
using System.Data.Common ;
using System.Data ;
using System.Text.RegularExpressions ;
using System.Reflection ;
using System.Reflection.Emit ;
using System.Text ;
using System.Text.RegularExpressions ;
using System.Threading ;
using MvcMiniProfiler ;
using System.Linq.Expressions ;
namespace PetaPoco
{
@@ -125,23 +123,29 @@ namespace PetaPoco
public string SequenceName { get ; set ; }
}
// Optionally provide and implementation of this to Database.Mapper
// Optionally provide an implementation of this to Database.Mapper
public interface IMapper
{
void GetTableInfo ( Type t , TableInfo ti ) ;
bool MapPropertyToColumn ( PropertyInfo pi , ref string columnName , ref bool resultColumn ) ;
Func < object , object > GetFromDbConverter ( DestinationInfo destinationInfo , Type S ourceType) ;
Func < object , object > GetFromDbConverter ( PropertyInfo pi , Type s ourceType) ;
Func < object , object > GetToDbConverter ( Type SourceType ) ;
}
public class DefaultMapper : IMapper
// This will be merged with IMapper in the next major version
public interface IMapper2 : IMapper
{
Func < object , object > GetFromDbConverter ( Type DestType , Type SourceType ) ;
}
public class DefaultMapper : IMapper2
{
public virtual void GetTableInfo ( Type t , TableInfo ti ) { }
public virtual bool MapPropertyToColumn ( PropertyInfo pi , ref string columnName , ref bool resultColumn )
{
return true ;
}
public virtual Func < object , object > GetFromDbConverter ( DestinationInfo destinationInfo , Type S ourceType)
public virtual Func < object , object > GetFromDbConverter ( PropertyInfo pi , Type s ourceType)
{
return null ;
}
@@ -149,24 +153,28 @@ namespace PetaPoco
{
return null ;
}
public virtual Func < object , object > GetFromDbConverter ( Type DestType , Type SourceType )
{
return null ;
}
}
public class DestinationInfo
{
public DestinationInfo( Type type )
{
Type = type ;
}
// public class DestinationInfo
// {
// public DestinationInfo( Type type)
// {
// Type = type;
// }
public DestinationInfo( PropertyInfo propertyInfo )
{
PropertyInfo = propertyInfo ;
Type = propertyInfo. PropertyType ;
}
// public DestinationInfo( PropertyInfo propertyInfo)
// {
// PropertyInfo = propertyInfo;
// Type = propertyInfo. PropertyType;
// }
public PropertyInfo PropertyInfo { get ; private set ; }
public Type Type { get ; private set ; }
}
// public PropertyInfo PropertyInfo { get; private set; }
// public Type Type { get; private set; }
// }
public interface IDatabaseQuery
{
@@ -240,6 +248,10 @@ namespace PetaPoco
object Insert ( object poco ) ;
int Update ( string tableName , string primaryKeyName , object poco , object primaryKeyValue ) ;
int Update ( string tableName , string primaryKeyName , object poco ) ;
int Update ( string tableName , string primaryKeyName , object poco , object primaryKeyValue , IEnumerable < string > columns ) ;
int Update ( string tableName , string primaryKeyName , object poco , IEnumerable < string > columns ) ;
int Update ( object poco , IEnumerable < string > columns ) ;
int Update ( object poco , object primaryKeyValue , IEnumerable < string > columns ) ;
int Update ( object poco ) ;
int Update ( object poco , object primaryKeyValue ) ;
int Update < T > ( string sql , params object [ ] args ) ;
@@ -317,7 +329,7 @@ namespace PetaPoco
Oracle ,
SQLite
}
DBType _dbType = DBType . SqlServerCE ;
DBType _dbType = DBType . SqlServer ;
// Common initialization
private void CommonConstruct ( )
@@ -355,8 +367,6 @@ namespace PetaPoco
// Open a connection (can be nested)
public void OpenSharedConnection ( )
{
using ( MvcMiniProfiler . MiniProfiler . StepStatic ( "OpenSharedConnection" ) )
{
if ( _sharedConnectionDepth = = 0 )
{
@@ -364,16 +374,18 @@ namespace PetaPoco
_sharedConnection . ConnectionString = _connectionString ;
_sharedConnection . Open ( ) ;
_sharedConnection = OnConnectionOpened ( _sharedConnection ) ;
if ( KeepConnectionAlive )
_sharedConnectionDepth + + ; // Make sure you call Dispose
}
_sharedConnectionDepth + + ;
}
}
/// <summary>
/// Close a previously opened connection
/// </summary>
// Close a previously opened connection
public void CloseSharedConnection ( )
{
if ( _sharedConnectionDepth > 0 )
@@ -381,6 +393,7 @@ namespace PetaPoco
_sharedConnectionDepth - - ;
if ( _sharedConnectionDepth = = 0 )
{
OnConnectionClosing ( _sharedConnection ) ;
_sharedConnection . Dispose ( ) ;
_sharedConnection = null ;
}
@@ -490,20 +503,32 @@ namespace PetaPoco
}
// Expand collections to parameter lists
if ( ( arg_val as IEnumerable ) ! = null & &
if ( ( arg_val as System . Collections . IEnumerable) ! = null & &
( arg_val as string ) = = null & &
( arg_val as byte [ ] ) = = null )
{
var sb = new StringBuilder ( ) ;
foreach ( var i in arg_val as IEnumerable )
foreach ( var i in arg_val as System . Collections . IEnumerable )
{
sb . Append ( ( sb . Length = = 0 ? "@" : ",@" ) + args_dest . Count . ToString ( ) ) ;
var indexOfExistingValue = args_dest . IndexOf ( i ) ;
if ( indexOfExistingValue > = 0 )
{
sb . Append ( ( sb . Length = = 0 ? "@" : ",@" ) + indexOfExistingValue ) ;
}
else
{
sb . Append ( ( sb . Length = = 0 ? "@" : ",@" ) + args_dest . Count ) ;
args_dest . Add ( i ) ;
}
}
return sb . ToString ( ) ;
}
else
{
var indexOfExistingValue = args_dest . IndexOf ( arg_val ) ;
if ( indexOfExistingValue > = 0 )
return "@" + indexOfExistingValue ;
args_dest . Add ( arg_val ) ;
return "@" + ( args_dest . Count - 1 ) . ToString ( ) ;
}
@@ -515,9 +540,9 @@ namespace PetaPoco
void AddParam ( IDbCommand cmd , object item , string ParameterPrefix )
{
// Convert value to from poco type to db type
if ( Mapper ! = null & & item ! = null )
if ( Database . Mapper ! = null & & item ! = null )
{
var fn = Mapper . GetToDbConverter ( item . GetType ( ) ) ;
var fn = Database . Mapper . GetToDbConverter ( item . GetType ( ) ) ;
if ( fn ! = null )
item = fn ( item ) ;
}
@@ -588,18 +613,15 @@ namespace PetaPoco
// Create a command
static Regex rxParamsPrefix = new Regex ( @"(?<!@)@\w+" , RegexOptions . Compiled ) ;
public IDbCommand CreateCommand ( IDbConnection connection , Sql sqlStatement )
IDbCommand CreateCommand ( IDbConnection connection , string sql , params object [ ] args )
{
var sql = sqlStatement . SQL ;
var args = sqlStatement . Arguments ;
// Perform parameter prefix replacements
if ( _paramPrefix ! = "@" )
sql = rxParamsPrefix . Replace ( sql , m = > _paramPrefix + m . Value . Substring ( 1 ) ) ;
sql = sql . Replace ( "@@" , "@" ) ; // <- double @@ escapes a single @
// Create the command and add parameters
IDbCommand cmd = _factory = = null ? connection . CreateCommand ( ) : _factory . CreateCommand ( ) ;
IDbCommand cmd = connection . CreateCommand ( ) ;
cmd . Connection = connection ;
cmd . CommandText = sql ;
cmd . Transaction = _transaction ;
@@ -621,20 +643,22 @@ namespace PetaPoco
}
// Create a command
IDbCommand CreateCommand( IDbConnection connection, string sql , params object[ ] args )
{
var sqlStatement = new Sql ( sql , args ) ;
return CreateCommand( connection, sqlStatement) ;
}
// IDbCommand CreateCommand( IDbConnection connection, string sql, params object[] args)
// {
// var sqlStatement = new Sql(sql, args) ;
// return CreateCommand( connection, sqlStatement) ;
// }
// Override this to log/capture exceptions
public virtual void OnException ( Exception x )
{
Debug . WriteLine ( x . ToString ( ) ) ;
Debug . WriteLine ( LastCommand ) ;
System . Diagnostics . Debug . WriteLine ( x . ToString ( ) ) ;
System . Diagnostics . Debug . WriteLine ( LastCommand ) ;
}
// Override this to log commands, or modify command before execution
public virtual IDbConnection OnConnectionOpened ( IDbConnection conn ) { return conn ; }
public virtual void OnConnectionClosing ( IDbConnection conn ) { }
public virtual void OnExecutingCommand ( IDbCommand cmd ) { }
public virtual void OnExecutedCommand ( IDbCommand cmd ) { }
@@ -644,16 +668,17 @@ namespace PetaPoco
return Execute ( new Sql ( sql , args ) ) ;
}
public int Execute ( Sql s ql)
{
using ( MiniProfiler . StepStatic ( "Peta Execute SQL" ) )
public int Execute ( Sql S ql)
{
var sql = Sql . SQL ;
var args = Sql . Arguments ;
try
{
OpenSharedConnection ( ) ;
try
{
using ( var cmd = CreateCommand ( _sharedConnection , sql ) )
using ( var cmd = CreateCommand ( _sharedConnection , sql , args ))
{
var result = cmd . ExecuteNonQuery ( ) ;
OnExecutedCommand ( cmd ) ;
@@ -671,7 +696,6 @@ namespace PetaPoco
throw ;
}
}
}
// Execute and cast a scalar property
public T ExecuteScalar < T > ( string sql , params object [ ] args )
@@ -679,16 +703,17 @@ namespace PetaPoco
return ExecuteScalar < T > ( new Sql ( sql , args ) ) ;
}
public T ExecuteScalar < T > ( Sql s ql)
{
using ( MiniProfiler . StepStatic ( "Peta ExecuteScalar<T>" ) )
public T ExecuteScalar < T > ( Sql S ql)
{
var sql = Sql . SQL ;
var args = Sql . Arguments ;
try
{
OpenSharedConnection ( ) ;
try
{
using ( var cmd = CreateCommand ( _sharedConnection , sql ) )
using ( var cmd = CreateCommand ( _sharedConnection , sql , args ))
{
object val = cmd . ExecuteScalar ( ) ;
OnExecutedCommand ( cmd ) ;
@@ -706,10 +731,9 @@ namespace PetaPoco
throw ;
}
}
}
Regex rxSelect = new Regex ( @"\A\s*(SELECT|EXECUTE|CALL)\s" , RegexOptions . Compiled | RegexOptions . Singleline | RegexOptions . IgnoreCase | RegexOptions . Multiline ) ;
Regex rxFrom = new Regex ( @"\A\s*FROM\s" , RegexOptions . Compiled | RegexOptions . Singleline | RegexOptions . IgnoreCase | RegexOptions . Multiline ) ;
static Regex rxSelect = new Regex ( @"\A\s*(SELECT|EXECUTE|CALL)\s" , RegexOptions . Compiled | RegexOptions . Singleline | RegexOptions . IgnoreCase | RegexOptions . Multiline ) ;
static Regex rxFrom = new Regex ( @"\A\s*FROM\s" , RegexOptions . Compiled | RegexOptions . Singleline | RegexOptions . IgnoreCase | RegexOptions . Multiline ) ;
string AddSelectClause < T > ( string sql )
{
if ( sql . StartsWith ( ";" ) )
@@ -734,9 +758,6 @@ namespace PetaPoco
// Return a typed list of pocos
public List < T > Fetch < T > ( string sql , params object [ ] args )
{
if ( EnableAutoSelect )
sql = AddSelectClause < T > ( sql ) ;
return Fetch < T > ( new Sql ( sql , args ) ) ;
}
@@ -745,26 +766,15 @@ namespace PetaPoco
return Query < T > ( sql ) . ToList ( ) ;
}
public List < T > Fetch < T > ( long page , long itemsPerPage , string sql , params object [ ] args )
{
string sqlCount , sqlPage ;
BuildPageQueries < T > ( page , itemsPerPage , sql , ref args , out sqlCount , out sqlPage ) ;
return Fetch < T > ( sqlPage , args ) ;
}
public List < T > Fetch < T > ( long page , long itemsPerPage , Sql sql )
{
return Fetch < T > ( page , itemsPerPage , sql . SQL , sql . Arguments ) ;
}
public List < T > Fetch < T > ( )
{
return Fetch < T > ( AddSelectClause < T > ( "" ) ) ;
return Fetch < T > ( "" ) ;
}
static Regex rxColumns = new Regex ( @"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b" , RegexOptions . IgnoreCase | RegexOptions . Multiline | RegexOptions . Singleline | RegexOptions . Compiled ) ;
static Regex rxOrderBy = new Regex ( @"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*" , RegexOptions . IgnoreCase | RegexOptions . Multiline | RegexOptions . Singleline | RegexOptions . Compiled ) ;
public static bool SplitSqlForPaging < T > ( string sql , out string sqlCount , out string sqlSelectRemoved , out string sqlOrderBy )
static Regex rxDistinct = new Regex ( @"\ADISTINCT\s" , RegexOptions . IgnoreCase | RegexOptions . Multiline | RegexOptions . Singleline | RegexOptions . Compiled ) ;
public static bool SplitSqlForPaging ( string sql , out string sqlCount , out string sqlSelectRemoved , out string sqlOrderBy )
{
sqlSelectRemoved = null ;
sqlCount = null ;
@@ -777,35 +787,34 @@ namespace PetaPoco
// Save column list and replace with COUNT(*)
Group g = m . Groups [ 1 ] ;
sqlCount = sql . Substring ( 0 , g . Index ) + "COUNT(*) " + sql . Substring ( g . Index + g . Length ) ;
sqlSelectRemoved = sql . Substring ( g . Index ) ;
// Look for an "ORDER BY <whatever>" clause or primarykey from pocodata
var data = PocoData . ForType ( typeof ( T ) ) ;
if ( rxDistinct . IsMatch ( sqlSelectRemoved ) )
sqlCount = sql . Substring ( 0 , g . Index ) + "COUNT(" + m . Groups [ 1 ] . ToString ( ) . Trim ( ) + ") " + sql . Substring ( g . Index + g . Length ) ;
else
sqlCount = sql . Substring ( 0 , g . Index ) + "COUNT(*) " + sql . Substring ( g . Index + g . Length ) ;
// Look for an "ORDER BY <whatever>" clause
m = rxOrderBy . Match ( sqlCount ) ;
if ( ! m . Success
& & ( string . IsNullOrEmpty ( data . TableInfo . PrimaryKey ) | |
( ! data . TableInfo . PrimaryKey . Split ( ',' ) . All ( x = > data . Columns . Values . Any ( y = > y . ColumnName . Equals ( x , StringComparison . OrdinalIgnoreCase ) ) ) ) ) )
if ( m . Success )
{
return false ;
}
g = m . Groups [ 0 ] ;
sqlOrderBy = m . Success ? g . ToString ( ) : "ORDER BY " + data . TableInfo . PrimaryKey ;
sqlOrderBy = g . ToString ( ) ;
sqlCount = sqlCount . Substring ( 0 , g . Index ) + sqlCount . Substring ( g . Index + g . Length ) ;
}
return true ;
}
private 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
sql = AddSelectClause < T > ( sql ) ;
// Split the SQL into the bits we need
string sqlSelectRemoved , sqlOrderBy ;
if ( ! SplitSqlForPaging < T > (sql , out sqlCount , out sqlSelectRemoved , out sqlOrderBy ) )
if ( ! SplitSqlForPaging ( sql , out sqlCount , out sqlSelectRemoved , out sqlOrderBy ) )
throw new Exception ( "Unable to parse SQL statement for paged query" ) ;
if ( _dbType = = DBType . Oracle & & sqlSelectRemoved . StartsWith ( "*" ) )
throw new Exception ( "Query must alias '*' when performing a paged query.\neg. select t.* from table t order by t.id" ) ;
@@ -813,10 +822,13 @@ namespace PetaPoco
// Build the SQL for the actual final result
if ( _dbType = = DBType . SqlServer | | _dbType = = DBType . Oracle )
{
var fromIndex = sqlSelectRemoved . IndexOf ( "from" , StringComparison . OrdinalIgnoreCase ) ;
sqlSelectRemoved = rxOrderBy . Replace ( sqlSelectRemoved , "" ) ;
sqlPage = str ing . Format ( "SELECT * FROM (SELECT {2}, ROW_NUMBER() OVER ({0}) peta_rn {1}) peta_paged WHERE peta_rn>@{3} AND peta_rn<=@{4}" ,
sqlOrderBy , sqlSelectRemoved . Substring ( fromIndex ) , sqlSelectRemoved . Substring ( 0 , fromIndex - 1 ) , args . Length , args . Length + 1 ) ;
if ( rxDi stinct . IsMatch ( sqlSelectRemoved ) )
{
sqlSelectRemoved = "peta_inner.* FROM (SELECT " + sqlSelectRemoved + ") peta_inner" ;
}
sqlPage = string . Format ( "SELECT * FROM (SELECT ROW_NUMBER() OVER ({0}) peta_rn, {1}) peta_paged WHERE peta_rn>@{2} AND peta_rn<=@{3}" ,
sqlOrderBy = = null ? "ORDER BY (SELECT NULL)" : sqlOrderBy , sqlSelectRemoved , args . Length , args . Length + 1 ) ;
args = args . Concat ( new object [ ] { skip , skip + take } ) . ToArray ( ) ;
}
else if ( _dbType = = DBType . SqlServerCE )
@@ -836,11 +848,7 @@ namespace PetaPoco
public Page < T > Page < T > ( long page , long itemsPerPage , string sql , params object [ ] args )
{
string sqlCount , sqlPage ;
long skip = ( page - 1 ) * itemsPerPage ;
long take = itemsPerPage ;
BuildPageQueries < T > ( skip , take , sql , ref args , out sqlCount , out sqlPage ) ;
BuildPageQueries < T > ( ( page - 1 ) * itemsPerPage , itemsPerPage , sql , ref args , out sqlCount , out sqlPage ) ;
// Save the one-time command time out and use it for both queries
int saveTimeout = OneTimeCommandTimeout ;
@@ -868,14 +876,21 @@ namespace PetaPoco
return Page < T > ( page , itemsPerPage , sql . SQL , sql . Arguments ) ;
}
public List < T > Fetch < T > ( long page , long itemsPerPage , string sql , params object [ ] args )
{
return SkipTake < T > ( ( page - 1 ) * itemsPerPage , itemsPerPage , sql , args ) ;
}
public List < T > Fetch < T > ( long page , long itemsPerPage , Sql sql )
{
return SkipTake < T > ( ( page - 1 ) * itemsPerPage , itemsPerPage , sql . SQL , sql . Arguments ) ;
}
public List < T > SkipTake < T > ( long skip , long take , string sql , params object [ ] args )
{
string sqlCount , sqlPage ;
BuildPageQueries < T > ( skip , take , sql , ref args , out sqlCount , out sqlPage ) ;
var result = Fetch < T > ( sqlPage , args ) ;
return result ;
return Fetch < T > ( sqlPage , args ) ;
}
public List < T > SkipTake < T > ( long skip , long take , Sql sql )
@@ -886,20 +901,21 @@ namespace PetaPoco
// Return an enumerable collection of pocos
public IEnumerable < T > Query < T > ( string sql , params object [ ] args )
{
if ( EnableAutoSelect )
sql = AddSelectClause < T > ( sql ) ;
return Query < T > ( new Sql ( sql , args ) ) ;
}
public IEnumerable < T > Query < T > ( Sql s ql)
{
using ( MiniProfiler . StepStatic ( "Peta Query SQL" ) )
public IEnumerable < T > Query < T > ( Sql S ql)
{
var sql = Sql . SQL ;
var args = Sql . Arguments ;
if ( EnableAutoSelect )
sql = AddSelectClause < T > ( sql ) ;
OpenSharedConnection ( ) ;
try
{
using ( var cmd = CreateCommand ( _sharedConnection , sql ) )
using ( var cmd = CreateCommand ( _sharedConnection , sql , args ))
{
IDataReader r ;
var pd = PocoData . ForType ( typeof ( T ) ) ;
@@ -916,9 +932,7 @@ namespace PetaPoco
using ( r )
{
var factory =
pd . GetFactory ( cmd . CommandText , _sharedConnection . ConnectionString , ForceDateTimesToUtc , 0 , r . FieldCount , r )
as Func < IDataReader , T > ;
var factory = pd . GetFactory ( cmd . CommandText , _sharedConnection . ConnectionString , ForceDateTimesToUtc , 0 , r . FieldCount , r ) as Func < IDataReader , T > ;
while ( true )
{
T poco ;
@@ -944,7 +958,6 @@ namespace PetaPoco
CloseSharedConnection ( ) ;
}
}
}
// Multi Fetch
public List < TRet > Fetch < T1 , T2 , TRet > ( Func < T1 , T2 , TRet > cb , string sql , params object [ ] args ) { return Query < T1 , T2 , TRet > ( cb , sql , args ) . ToList ( ) ; }
@@ -1136,7 +1149,7 @@ namespace PetaPoco
// Various cached stuff
static Dictionary < string , object > MultiPocoFactories = new Dictionary < string , object > ( ) ;
static Dictionary < string , object > AutoMappers = new Dictionary < string , object > ( ) ;
static ReaderWriterLockSlim RWLock = new ReaderWriterLockSlim ( ) ;
static System . Threading . ReaderWriterLockSlim RWLock = new System . Threading . ReaderWriterLockSlim ( ) ;
// Get (or create) the multi-poco factory for a query
Func < IDataReader , object , TRet > GetMultiPocoFactory < TRet > ( Type [ ] types , string sql , IDataReader r )
@@ -1192,8 +1205,6 @@ namespace PetaPoco
// Actual implementation of the multi-poco query
public IEnumerable < TRet > Query < TRet > ( Type [ ] types , object cb , string sql , params object [ ] args )
{
using ( MiniProfiler . StepStatic ( "Peta Query Type[]" ) )
{
OpenSharedConnection ( ) ;
try
@@ -1253,7 +1264,6 @@ namespace PetaPoco
CloseSharedConnection ( ) ;
}
}
}
public bool Exists < T > ( object primaryKey )
{
@@ -1340,7 +1350,7 @@ namespace PetaPoco
public string EscapeTableName ( string str )
{
// Assume table names with "dot", or opening sq is already escaped
// Assume table names with "dot" are already escaped
return str . IndexOf ( '.' ) > = 0 ? str : EscapeSqlIdentifier ( str ) ;
}
@@ -1352,9 +1362,11 @@ namespace PetaPoco
return string . Format ( "`{0}`" , str ) ;
case DBType . PostgreSQL :
case DBType . Oracle :
return string . Format ( "\"{0}\"" , str ) ;
case DBType . Oracle :
return string . Format ( "\"{0}\"" , str . ToUpperInvariant ( ) ) ;
default :
return string . Format ( "[{0}]" , str ) ;
}
@@ -1369,8 +1381,6 @@ namespace PetaPoco
// 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 )
{
using ( MiniProfiler . StepStatic ( "Peta Insert " + tableName ) )
{
try
{
@@ -1421,15 +1431,17 @@ namespace PetaPoco
string . Join ( "," , values . ToArray ( ) )
) ;
object id ;
if ( ! autoIncrement )
{
DoPreExecute ( cmd ) ;
cmd . ExecuteNonQuery ( ) ;
OnExecutedCommand ( cmd ) ;
return true ;
id = true ;
}
object id ;
else
{
switch ( _dbType )
{
@@ -1514,6 +1526,7 @@ namespace PetaPoco
pc . SetValue ( poco , pc . ChangeType ( id ) ) ;
}
}
}
// Assign the Version column
if ( ! string . IsNullOrEmpty ( versionName ) )
@@ -1539,7 +1552,6 @@ namespace PetaPoco
throw ;
}
}
}
// Insert an annotated poco object
public object Insert ( object poco )
@@ -1561,10 +1573,14 @@ namespace PetaPoco
}
}
// Update a record with values from a poco. primary key value can be either supplied or read from the poco
public int Update ( string tableName , string primaryKeyName , object poco , object primaryKeyValue )
{
using ( MiniProfiler . StepStatic ( "Peta Update " + tableName ) )
return Update ( tableName , primaryKeyName , poco , primaryKeyValue , null ) ;
}
// Update a record with values from a poco. primary key value can be either supplied or read from the poco
public int Update ( string tableName , string primaryKeyName , object poco , object primaryKeyValue , IEnumerable < string > columns )
{
try
{
@@ -1594,6 +1610,9 @@ namespace PetaPoco
if ( i . Value . ResultColumn )
continue ;
if ( ! i . Value . VersionColumn & & columns ! = null & & ! columns . Contains ( i . Value . ColumnName , StringComparer . OrdinalIgnoreCase ) )
continue ;
object value = i . Value . PropertyInfo . GetValue ( poco , null ) ;
if ( i . Value . VersionColumn )
@@ -1612,9 +1631,9 @@ namespace PetaPoco
AddParam ( cmd , value , _paramPrefix ) ;
}
cmd . CommandText = string . Format ( "UPDATE {0} SET {1} WHERE {2}" ,
EscapeSqlIdentifier ( tableName ) , sb . ToString ( ) ,
BuildPrimaryKeySql ( primaryKeyValuePairs , ref index ) ) ;
EscapeTableName ( tableName ) , sb . ToString ( ) , BuildPrimaryKeySql ( primaryKeyValuePairs , ref index ) ) ;
foreach ( var keyValue in primaryKeyValuePairs )
{
@@ -1623,8 +1642,7 @@ namespace PetaPoco
if ( ! string . IsNullOrEmpty ( versionName ) )
{
cmd . CommandText + = string . Format ( " AND {0} = {1}{2}" , EscapeSqlIdentifier ( versionName ) , _paramPrefix ,
index + + ) ;
cmd . CommandText + = string . Format ( " AND {0} = {1}{2}" , EscapeSqlIdentifier ( versionName ) , _paramPrefix , index + + ) ;
AddParam ( cmd , versionValue , _paramPrefix ) ;
}
@@ -1635,14 +1653,11 @@ namespace PetaPoco
OnExecutedCommand ( cmd ) ;
// Set Version
if ( ! string . IsNullOrEmpty ( versionName ) )
{
if ( ! string . IsNullOrEmpty ( versionName ) ) {
PocoColumn pc ;
if ( pd . Columns . TryGetValue ( versionName , out pc ) )
{
pc . PropertyInfo . SetValue ( poco ,
Convert . ChangeType ( Convert . ToInt64 ( versionValue ) + 1 ,
pc . PropertyInfo . PropertyType ) , null ) ;
pc . PropertyInfo . SetValue ( poco , Convert . ChangeType ( Convert . ToInt64 ( versionValue ) + 1 , pc . PropertyInfo . PropertyType ) , null ) ;
}
}
@@ -1660,7 +1675,6 @@ namespace PetaPoco
throw ;
}
}
}
private string BuildPrimaryKeySql ( Dictionary < string , object > primaryKeyValuePair , ref int index )
{
@@ -1696,15 +1710,29 @@ namespace PetaPoco
return Update ( tableName , primaryKeyName , poco , null ) ;
}
public int Update ( string tableName , string primaryKeyName , object poco , IEnumerable < string > columns )
{
return Update ( tableName , primaryKeyName , poco , null , columns ) ;
}
public int Update ( object poco , IEnumerable < string > columns )
{
return Update ( poco , null , columns ) ;
}
public int Update ( object poco )
{
return Update ( poco , null ) ;
return Update ( poco , null , null ) ;
}
public int Update ( object poco , object primaryKeyValue )
{
return Update ( poco , primaryKeyValue , null ) ;
}
public int Update ( object poco , object primaryKeyValue , IEnumerable < string > columns )
{
var pd = PocoData . ForType ( poco . GetType ( ) ) ;
return Update ( pd . TableInfo . TableName , pd . TableInfo . PrimaryKey , poco , primaryKeyValue ) ;
return Update ( pd . TableInfo . TableName , pd . TableInfo . PrimaryKey , poco , primaryKeyValue , columns );
}
public int Update < T > ( string sql , params object [ ] args )
@@ -1947,7 +1975,7 @@ namespace PetaPoco
public virtual object GetValue ( object target ) { return PropertyInfo . GetValue ( target , null ) ; }
public virtual object ChangeType ( object val ) { return Convert . ChangeType ( val , PropertyInfo . PropertyType ) ; }
}
internal class ExpandoColumn : PocoColumn
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 )
@@ -1958,7 +1986,7 @@ namespace PetaPoco
}
public override object ChangeType ( object val ) { return val ; }
}
internal class PocoData
public class PocoData
{
public static PocoData ForObject ( object o , string primaryKeyName )
{
@@ -1983,7 +2011,7 @@ namespace PetaPoco
#endif
return ForType ( t ) ;
}
static ReaderWriterLockSlim RWLock = new ReaderWriterLockSlim ( ) ;
static System . Threading . ReaderWriterLockSlim RWLock = new System . Threading . ReaderWriterLockSlim ( ) ;
public static PocoData ForType ( Type t )
{
#if ! PETAPOCO_NO_DYNAMIC
@@ -2047,8 +2075,8 @@ namespace PetaPoco
TableInfo . AutoIncrement = TableInfo . AutoIncrement ? ! TableInfo . PrimaryKey . Contains ( ',' ) : TableInfo . AutoIncrement ;
// Call column mapper
if ( Mapper ! = null )
Mapper . GetTableInfo ( t , TableInfo ) ;
if ( Database . Mapper ! = null )
Database . Mapper . GetTableInfo ( t , TableInfo ) ;
// Work out bound properties
bool ExplicitColumns = t . GetCustomAttributes ( typeof ( ExplicitColumnsAttribute ) , true ) . Length > 0 ;
@@ -2084,7 +2112,7 @@ namespace PetaPoco
if ( pc . ColumnName = = null )
{
pc . ColumnName = pi . Name ;
if ( Mapper ! = null & & ! Mapper . MapPropertyToColumn ( pi , ref pc . ColumnName , ref pc . ResultColumn ) )
if ( Database . Mapper ! = null & & ! Database . Mapper. MapPropertyToColumn ( pi , ref pc . ColumnName , ref pc . ResultColumn ) )
continue ;
}
@@ -2236,8 +2264,10 @@ namespace PetaPoco
{
// Get the PocoColumn for this db column, ignore if not known
PocoColumn pc ;
if ( ! Columns . TryGetValue ( r . GetName ( i ) , out pc ) )
if ( ! Columns . TryGetValue ( r . GetName ( i ) , out pc ) & & ! Columns . TryGetValue ( r . GetName ( i ) . Replace ( "_" , "" ) , out pc ) )
{
continue ;
}
// Get the source type for this column
var srcType = r . GetFieldType ( i ) ;
@@ -2301,6 +2331,13 @@ namespace PetaPoco
il . MarkLabel ( lblNext ) ;
}
var fnOnLoaded = RecurseInheritedTypes < MethodInfo > ( type , ( x ) = > x . GetMethod ( "OnLoaded" , BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic , null , new Type [ 0 ] , null ) ) ;
if ( fnOnLoaded ! = null )
{
il . Emit ( OpCodes . Dup ) ;
il . Emit ( OpCodes . Callvirt , fnOnLoaded ) ;
}
}
il . Emit ( OpCodes . Ret ) ;
@@ -2336,12 +2373,20 @@ namespace PetaPoco
Func < object , object > converter = null ;
// Get converter from the mapper
if ( Mapper ! = null )
if ( Database . Mapper ! = null )
{
DestinationInfo destinationInfo = pc ! = null
? new DestinationInfo ( pc . PropertyInfo )
: new DestinationInfo ( dst Type) ;
converter = Mapper . GetFromDbConverter ( destinationInfo , srcType ) ;
if ( pc ! = null )
{
converter = Database . Mapper . GetFromDbConverter ( pc . PropertyInfo , src Type) ;
}
else
{
var m2 = Database . Mapper as IMapper2 ;
if ( m2 ! = null )
{
converter = m2 . GetFromDbConverter ( dstType , srcType ) ;
}
}
}
// Standard DateTime->Utc mapper
@@ -2369,6 +2414,19 @@ namespace PetaPoco
}
static T RecurseInheritedTypes < T > ( Type t , Func < Type , T > cb )
{
while ( t ! = null )
{
T info = cb ( t ) ;
if ( info ! = null )
return info ;
t = t . BaseType ;
}
return default ( T ) ;
}
static Dictionary < Type , PocoData > m_PocoDatas = new Dictionary < Type , PocoData > ( ) ;
static List < Func < object , object > > m_Converters = new List < Func < object , object > > ( ) ;
static MethodInfo fnGetValue = typeof ( IDataRecord ) . GetMethod ( "GetValue" , new Type [ ] { typeof ( int ) } ) ;
@@ -2411,7 +2469,7 @@ namespace PetaPoco
_db . BeginTransaction ( ) ;
}
public void Complete ( )
public virtual void Complete ( )
{
_db . CompleteTransaction ( ) ;
_db = null ;