306 lines
13 KiB
C#
306 lines
13 KiB
C#
//===============================================================================
|
|
// Microsoft patterns & practices Enterprise Library
|
|
// Data Access Application Block
|
|
//===============================================================================
|
|
// Copyright © Microsoft Corporation. All rights reserved.
|
|
// Adapted from ACA.NET with permission from Avanade Inc.
|
|
// ACA.NET copyright © Avanade Inc. All rights reserved.
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
|
|
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
|
|
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//===============================================================================
|
|
|
|
using System;
|
|
using System.Data;
|
|
using System.Data.Common;
|
|
using System.Data.SqlClient;
|
|
using System.Xml;
|
|
//using GZTW.Common;
|
|
|
|
namespace GZTW.Data.Sql
|
|
{
|
|
/// <summary>
|
|
/// <para>Represents a Sql Server Database.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Internally uses Sql Server .NET Managed Provider from Microsoft (System.Data.SqlClient) to connect to the database.
|
|
/// </para>
|
|
/// </remarks>
|
|
public class SqlDatabase : GZTWDatabase
|
|
{
|
|
/// <summary>
|
|
/// Initialize a new instance of the <see cref="SqlDatabase"/> class.
|
|
/// </summary>
|
|
public SqlDatabase() : base()
|
|
{
|
|
}
|
|
|
|
public override void ClearPool()
|
|
{
|
|
//not implemented, for firebird only for now
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the DataBaseType enum for the active db type
|
|
/// Used by higher layers when some DB specific code needs to be
|
|
/// executed
|
|
/// </summary>
|
|
/// <value>
|
|
/// <para>DataBaseType enumeration value</para>
|
|
/// </value>
|
|
public override DataBaseType DBType
|
|
{
|
|
get
|
|
{
|
|
return DataBaseType.MSSQL;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the schema fingerprint for database
|
|
/// </summary>
|
|
public override string SchemaFingerPrint
|
|
{
|
|
get
|
|
{
|
|
string _fingerprint = "";
|
|
using (SqlConnection cn = new SqlConnection(ConnectionString))
|
|
{
|
|
try
|
|
{
|
|
cn.Open();
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
DataTable t = new DataTable();
|
|
new SqlDataAdapter("select name from sys.tables order by name", cn).Fill(t);
|
|
foreach (DataRow drTable in t.Rows)
|
|
{
|
|
//My development database has this table in it for some reason
|
|
//should be ignored
|
|
if (drTable[0].ToString() == "sysdiagrams" || drTable[0].ToString().ToLowerInvariant().Contains("dtproperties")) continue;
|
|
|
|
sb.Append(drTable[0].ToString());
|
|
sb.Append("\r\n");
|
|
|
|
DataTable tColumns = new DataTable();
|
|
new SqlDataAdapter("SELECT c.name AS column_name, t.name AS type_name " +
|
|
"FROM sys.columns AS c " +
|
|
"JOIN sys.types AS t ON c.user_type_id=t.user_type_id " +
|
|
"WHERE c.object_id = OBJECT_ID('"+ drTable[0].ToString()+"') " +
|
|
"ORDER BY c.name; ", cn).Fill(tColumns);
|
|
|
|
foreach (DataRow drColumn in tColumns.Rows)
|
|
{
|
|
sb.Append("\t");
|
|
sb.Append(drColumn["column_name"].ToString());
|
|
//sb.Append(" ");
|
|
//sb.Append(drColumn["type_name"].ToString());
|
|
sb.Append("\r\n");
|
|
}
|
|
}
|
|
|
|
_fingerprint = sb.ToString().Trim();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
if (cn != null)
|
|
cn.Close();
|
|
}
|
|
}
|
|
|
|
return _fingerprint;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Gets the parameter token used to delimit parameters for the Sql Database.</para>
|
|
/// </summary>
|
|
/// <value>
|
|
/// <para>The '@' symbol.</para>
|
|
/// </value>
|
|
protected override char ParameterToken
|
|
{
|
|
get { return '@'; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Get the connection for this database.</para>
|
|
/// <seealso cref="IDbConnection"/>
|
|
/// <seealso cref="SqlConnection"/>
|
|
/// </summary>
|
|
/// <returns>
|
|
/// <para>The <see cref="SqlConnection"/> for this database.</para>
|
|
/// </returns>
|
|
public override IDbConnection GetConnection()
|
|
{
|
|
return new SqlConnection(ConnectionString);
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Create a <see cref="SqlCommandWrapper"/> for a stored procedure.</para>
|
|
/// </summary>
|
|
/// <param name="storedProcedureName"><para>The name of the stored procedure.</para></param>
|
|
/// <returns><para>The <see cref="SqlCommandWrapper"/> for the stored procedure.</para></returns>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// <para><paramref name="storedProcedureName"/> can not be <see langword="null"/> (Nothing in Visual Basic).</para>
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// <para><paramref name="storedProcedureName"/> hast not been initialized.</para>
|
|
/// </exception>
|
|
// public override DBCommandWrapper GetStoredProcCommandWrapper(string storedProcedureName)
|
|
// {
|
|
// ArgumentValidation.CheckForNullReference(storedProcedureName, "storedProcedureName");
|
|
// ArgumentValidation.CheckForEmptyString(storedProcedureName, "storedProcedureName");
|
|
//
|
|
// return new SqlCommandWrapper(storedProcedureName, CommandType.StoredProcedure, ParameterToken);
|
|
// }
|
|
|
|
/// <summary>
|
|
/// <para>Create an <see cref="SqlCommandWrapper"/> for a stored procedure.</para>
|
|
/// </summary>
|
|
/// <param name="storedProcedureName"><para>The name of the stored procedure.</para></param>
|
|
/// <param name="parameterValues"><para>The list of parameters for the procedure.</para></param>
|
|
/// <returns><para>The <see cref="SqlCommandWrapper"/> for the stored procedure.</para></returns>
|
|
/// <remarks>
|
|
/// <para>The parameters for the stored procedure will be discovered and the values are assigned in positional order.</para>
|
|
/// </remarks>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// <para><paramref name="storedProcedureName"/> can not be <see langword="null"/> (Nothing in Visual Basic).</para>
|
|
/// <para>- or -</para>
|
|
/// <para><paramref name="parameterValues"/> can not be <see langword="null"/> (Nothing in Visual Basic).</para>
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// <para><paramref name="storedProcedureName"/> hast not been initialized.</para>
|
|
/// </exception>
|
|
// public override DBCommandWrapper GetStoredProcCommandWrapper(string storedProcedureName, params object[] parameterValues)
|
|
// {
|
|
// ArgumentValidation.CheckForNullReference(storedProcedureName, "storedProcedureName");
|
|
// ArgumentValidation.CheckForEmptyString(storedProcedureName, "storedProcedureName");
|
|
// ArgumentValidation.CheckForNullReference(parameterValues, "parameterValues");
|
|
//
|
|
// return new SqlCommandWrapper(storedProcedureName, CommandType.StoredProcedure, ParameterToken, parameterValues);
|
|
// }
|
|
|
|
/// <summary>
|
|
/// <para>Create an <see cref="SqlCommandWrapper"/> for a SQL query.</para>
|
|
/// </summary>
|
|
/// <param name="query"><para>The text of the query.</para></param>
|
|
/// <returns><para>The <see cref="SqlCommandWrapper"/> for the SQL query.</para></returns>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// <para><paramref name="query"/> can not be <see langword="null"/> (Nothing in Visual Basic).</para>
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// <para><paramref name="query"/> hast not been initialized.</para>
|
|
/// </exception>
|
|
public override DBCommandWrapper GetSqlStringCommandWrapper(string query)
|
|
{
|
|
ArgumentValidation.CheckForNullReference(query, "query");
|
|
ArgumentValidation.CheckForEmptyString(query, "query");
|
|
|
|
return new SqlCommandWrapper(query, CommandType.Text, ParameterToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Create a <see cref="SqlDataAdapter"/> with the given update behavior and connection.</para>
|
|
/// </summary>
|
|
/// <param name="updateBehavior">
|
|
/// <para>One of the <see cref="UpdateBehavior"/> values.</para>
|
|
/// </param>
|
|
/// <param name="connection">
|
|
/// <para>The open connection to the database.</para>
|
|
/// </param>
|
|
/// <returns>An <see cref="SqlDataAdapter"/>.</returns>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// <para><paramref name="connection"/> can not be <see langword="null"/> (Nothing in Visual Basic).</para>
|
|
/// </exception>
|
|
protected override DbDataAdapter GetDataAdapter(UpdateBehavior updateBehavior, IDbConnection connection)
|
|
{
|
|
string queryStringToBeFilledInLater = String.Empty;
|
|
SqlDataAdapter adapter = new SqlDataAdapter(queryStringToBeFilledInLater, (SqlConnection)connection);
|
|
|
|
if (updateBehavior == UpdateBehavior.Continue)
|
|
{
|
|
adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnSqlRowUpdated);
|
|
}
|
|
return adapter;
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Executes the <see cref="SqlCommandWrapper"/> and returns an <see cref="XmlReader"/>.</para>
|
|
/// </summary>
|
|
/// <param name="command">
|
|
/// <para>The <see cref="SqlCommandWrapper"/> to execute.</para>
|
|
/// </param>
|
|
/// <returns>
|
|
/// <para>An <see cref="XmlReader"/> object.</para>
|
|
/// </returns>
|
|
public XmlReader ExecuteXmlReader(SqlCommandWrapper command)
|
|
{
|
|
IDbConnection connection = OpenConnection();
|
|
PrepareCommand(command, connection);
|
|
SqlCommand sqlCommand = command.Command as SqlCommand;
|
|
return DoExecuteXmlReader(sqlCommand);
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Executes the <see cref="SqlCommandWrapper"/> in a transaction and returns an <see cref="XmlReader"/>.</para>
|
|
/// </summary>
|
|
/// <param name="command">
|
|
/// <para>The <see cref="SqlCommandWrapper"/> to execute.</para>
|
|
/// </param>
|
|
/// <param name="transaction">
|
|
/// <para>The <see cref="IDbTransaction"/> to execute the command within.</para>
|
|
/// </param>
|
|
/// <returns>
|
|
/// <para>An <see cref="XmlReader"/> object.</para>
|
|
/// </returns>
|
|
public XmlReader ExecuteXmlReader(SqlCommandWrapper command, IDbTransaction transaction)
|
|
{
|
|
PrepareCommand(command, transaction);
|
|
|
|
SqlCommand sqlCommand = command.Command as SqlCommand;
|
|
return DoExecuteXmlReader(sqlCommand);
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// Execute the actual Xml Reader call.
|
|
/// </devdoc>
|
|
private XmlReader DoExecuteXmlReader(SqlCommand sqlCommand)
|
|
{
|
|
try
|
|
{
|
|
DateTime startTime = DateTime.Now;
|
|
XmlReader reader = sqlCommand.ExecuteXmlReader();
|
|
//Instrumentation.CommandExecuted(startTime);
|
|
return reader;
|
|
}
|
|
catch
|
|
{
|
|
//Instrumentation.CommandFailed(sqlCommand.CommandText, ConnectionStringNoCredentials);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// Listens for the RowUpdate event on a dataadapter to support UpdateBehavior.Continue
|
|
/// </devdoc>
|
|
private void OnSqlRowUpdated(object sender, SqlRowUpdatedEventArgs rowThatCouldNotBeWritten)
|
|
{
|
|
if (rowThatCouldNotBeWritten.RecordsAffected == 0)
|
|
{
|
|
if (rowThatCouldNotBeWritten.Errors != null)
|
|
{
|
|
rowThatCouldNotBeWritten.Row.RowError = SR.ExceptionMessageUpdateDataSetRowFailure;
|
|
rowThatCouldNotBeWritten.Status = UpdateStatus.SkipCurrentRow;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |