2010-09-17 08:44:25 +00:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Umbraco Data Layer
* MIT Licensed work
* <EFBFBD> 2008 Ruben Verborgh
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
using System ;
2012-07-17 03:14:22 +06:00
using System.Collections.Generic ;
2010-09-17 08:44:25 +00:00
using System.Data ;
using System.Data.SqlServerCe ;
2012-07-17 03:14:22 +06:00
using System.Linq ;
2010-09-17 08:44:25 +00:00
using System.Xml ;
using System.Diagnostics ;
using umbraco.DataLayer ;
using umbraco.DataLayer.SqlHelpers.SqlServer ;
namespace SqlCE4Umbraco
{
/// <summary>
/// Sql Helper for an SQL Server database.
/// </summary>
public class SqlCEHelper : SqlHelper < SqlCeParameter >
{
/// <summary>
/// Initializes a new instance of the <see cref="SqlCEHelper"/> class.
/// </summary>
/// <param name="connectionString">The connection string.</param>
public SqlCEHelper ( string connectionString ) : base ( connectionString )
{
m_Utility = new SqlCEUtility ( this ) ;
}
2012-07-17 00:52:08 +06:00
/// <summary>
/// Checks if the actual database exists, if it doesn't then it will create it
/// </summary>
internal void CreateEmptyDatabase ( )
{
var localConnection = new SqlCeConnection ( ConnectionString ) ;
2012-08-24 13:56:39 -01:00
if ( ! System . IO . File . Exists ( ReplaceDataDirectory ( localConnection . Database ) ) )
2012-07-17 00:52:08 +06:00
{
2016-07-06 09:37:52 +02:00
using ( var sqlCeEngine = new SqlCeEngine ( ConnectionString ) )
{
sqlCeEngine . CreateDatabase ( ) ;
}
2012-07-17 00:52:08 +06:00
}
}
2012-07-17 03:14:22 +06:00
/// <summary>
/// Most likely only will be used for unit tests but will remove all tables from the database
/// </summary>
internal void ClearDatabase ( )
{
2013-02-20 14:38:28 -01:00
// drop constraints before tables to avoid exceptions
// looping on try/catching exceptions was not really nice
// http://stackoverflow.com/questions/536350/drop-all-the-tables-stored-procedures-triggers-constriants-and-all-the-depend
2012-07-17 03:14:22 +06:00
var localConnection = new SqlCeConnection ( ConnectionString ) ;
2012-10-02 02:33:19 +05:00
if ( System . IO . File . Exists ( ReplaceDataDirectory ( localConnection . Database ) ) )
2012-07-17 03:14:22 +06:00
{
2013-02-20 14:38:28 -01:00
List < string > tables ;
// drop foreign keys
// SQL may need "where constraint_catalog=DB_NAME() and ..."
tables = new List < string > ( ) ;
using ( var reader = ExecuteReader ( "select table_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' order by table_name" ) )
{
while ( reader . Read ( ) ) tables . Add ( reader . GetString ( "table_name" ) . Trim ( ) ) ;
}
foreach ( var table in tables )
2012-07-17 03:14:22 +06:00
{
2013-02-20 14:38:28 -01:00
var constraints = new List < string > ( ) ;
using ( var reader = ExecuteReader ( "select constraint_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' and table_name = '" + table + "' order by constraint_name" ) )
{
while ( reader . Read ( ) ) constraints . Add ( reader . GetString ( "constraint_name" ) . Trim ( ) ) ;
}
foreach ( var constraint in constraints )
2012-07-17 03:14:22 +06:00
{
2013-02-20 14:38:28 -01:00
// SQL may need "[dbo].[table]"
ExecuteNonQuery ( "alter table [" + table + "] drop constraint [" + constraint + "]" ) ;
2012-07-17 03:14:22 +06:00
}
}
2013-02-20 14:38:28 -01:00
// drop primary keys
// SQL may need "where constraint_catalog=DB_NAME() and ..."
tables = new List < string > ( ) ;
using ( var reader = ExecuteReader ( "select table_name from information_schema.table_constraints where constraint_type = 'PRIMARY KEY' order by table_name" ) )
2012-07-17 03:14:22 +06:00
{
2013-02-20 14:38:28 -01:00
while ( reader . Read ( ) ) tables . Add ( reader . GetString ( "table_name" ) . Trim ( ) ) ;
}
2012-07-17 03:14:22 +06:00
2013-02-20 14:38:28 -01:00
foreach ( var table in tables )
{
var constraints = new List < string > ( ) ;
using ( var reader = ExecuteReader ( "select constraint_name from information_schema.table_constraints where constraint_type = 'PRIMARY KEY' and table_name = '" + table + "' order by constraint_name" ) )
{
while ( reader . Read ( ) ) constraints . Add ( reader . GetString ( "constraint_name" ) . Trim ( ) ) ;
}
foreach ( var constraint in constraints )
{
// SQL may need "[dbo].[table]"
ExecuteNonQuery ( "alter table [" + table + "] drop constraint [" + constraint + "]" ) ;
2012-07-17 03:14:22 +06:00
}
2012-08-24 13:56:39 -01:00
}
2013-02-20 14:38:28 -01:00
// drop tables
tables = new List < string > ( ) ;
using ( var reader = ExecuteReader ( "select table_name from information_schema.tables where table_type <> 'VIEW' order by table_name" ) )
{
while ( reader . Read ( ) ) tables . Add ( reader . GetString ( "table_name" ) . Trim ( ) ) ;
}
foreach ( var table in tables )
{
ExecuteNonQuery ( "drop table [" + table + "]" ) ;
}
}
}
/// <summary>
/// Drops all foreign keys on a table.
/// </summary>
/// <param name="table">The name of the table.</param>
/// <remarks>To be used in unit tests.</remarks>
internal void DropForeignKeys ( string table )
{
var constraints = new List < string > ( ) ;
using ( var reader = ExecuteReader ( "select constraint_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' and table_name = '" + table + "' order by constraint_name" ) )
{
while ( reader . Read ( ) ) constraints . Add ( reader . GetString ( "constraint_name" ) . Trim ( ) ) ;
}
foreach ( var constraint in constraints )
{
// SQL may need "[dbo].[table]"
ExecuteNonQuery ( "alter table [" + table + "] drop constraint [" + constraint + "]" ) ;
2012-08-24 13:56:39 -01:00
}
}
/// <summary>
/// Replaces the data directory with a local path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>A local path with the resolved 'DataDirectory' mapping.</returns>
private string ReplaceDataDirectory ( string path )
{
if ( ! string . IsNullOrWhiteSpace ( path ) & & path . Contains ( "|DataDirectory|" ) )
{
var dataDirectory = AppDomain . CurrentDomain . GetData ( "DataDirectory" ) as string ;
if ( ! string . IsNullOrEmpty ( dataDirectory ) )
{
2013-03-06 14:09:01 -01:00
path = path . Contains ( @"|\" )
? path . Replace ( "|DataDirectory|" , dataDirectory )
: path . Replace ( "|DataDirectory|" , dataDirectory + System . IO . Path . DirectorySeparatorChar ) ;
2012-08-24 13:56:39 -01:00
}
2012-07-17 03:14:22 +06:00
}
2012-08-24 13:56:39 -01:00
return path ;
2012-07-17 03:14:22 +06:00
}
2010-09-17 08:44:25 +00:00
/// <summary>
/// Creates a new parameter for use with this specific implementation of ISqlHelper.
/// </summary>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="value">Value of the parameter.</param>
/// <returns>A new parameter of the correct type.</returns>
/// <remarks>Abstract factory pattern</remarks>
public override IParameter CreateParameter ( string parameterName , object value )
{
return new SqlCEParameter ( parameterName , value ) ;
}
/// <summary>
/// Executes a command that returns a single value.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>The return value of the command.</returns>
protected override object ExecuteScalar ( string commandText , SqlCeParameter [ ] parameters )
{
2016-09-15 12:14:25 +02:00
#if DEBUG & & DebugDataLayer
2010-09-17 08:44:25 +00:00
// Log Query Execution
Trace . TraceInformation ( GetType ( ) . Name + " SQL ExecuteScalar: " + commandText ) ;
2016-09-15 12:14:25 +02:00
#endif
using ( var cc = UseCurrentConnection )
{
return SqlCeApplicationBlock . ExecuteScalar (
( SqlCeConnection ) cc . Connection , ( SqlCeTransaction ) cc . Transaction ,
CommandType . Text , commandText , parameters ) ;
}
2010-09-17 08:44:25 +00:00
}
/// <summary>
/// Executes a command and returns the number of rows affected.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>
/// The number of rows affected by the command.
/// </returns>
protected override int ExecuteNonQuery ( string commandText , SqlCeParameter [ ] parameters )
{
2016-09-15 12:14:25 +02:00
#if DEBUG & & DebugDataLayer
2010-09-17 08:44:25 +00:00
// Log Query Execution
Trace . TraceInformation ( GetType ( ) . Name + " SQL ExecuteNonQuery: " + commandText ) ;
2016-09-15 12:14:25 +02:00
#endif
2010-09-17 08:44:25 +00:00
2016-09-15 12:14:25 +02:00
using ( var cc = UseCurrentConnection )
{
return SqlCeApplicationBlock . ExecuteNonQuery (
( SqlCeConnection ) cc . Connection , ( SqlCeTransaction ) cc . Transaction ,
CommandType . Text , commandText , parameters ) ;
}
2010-09-17 08:44:25 +00:00
}
/// <summary>
/// Executes a command and returns a records reader containing the results.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>
/// A data reader containing the results of the command.
/// </returns>
protected override IRecordsReader ExecuteReader ( string commandText , SqlCeParameter [ ] parameters )
{
2016-09-15 12:14:25 +02:00
#if DEBUG & & DebugDataLayer
2010-09-17 08:44:25 +00:00
// Log Query Execution
Trace . TraceInformation ( GetType ( ) . Name + " SQL ExecuteReader: " + commandText ) ;
2016-09-15 12:14:25 +02:00
#endif
2010-09-17 08:44:25 +00:00
2016-09-15 12:14:25 +02:00
using ( var cc = UseCurrentConnection )
{
return new SqlCeDataReaderHelper ( SqlCeApplicationBlock . ExecuteReader (
( SqlCeConnection ) cc . Connection , ( SqlCeTransaction ) cc . Transaction ,
CommandType . Text , commandText , parameters ) ) ;
}
2010-09-17 08:44:25 +00:00
}
2014-10-24 10:32:41 +02:00
internal IRecordsReader ExecuteReader ( string commandText )
{
return ExecuteReader ( commandText , new SqlCEParameter ( string . Empty , string . Empty ) ) ;
}
internal int ExecuteNonQuery ( string commandText )
{
return ExecuteNonQuery ( commandText , new SqlCEParameter ( string . Empty , string . Empty ) ) ;
}
2010-09-17 08:44:25 +00:00
}
}