You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel.MsSql/SqlDbProvider.cs

451 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
namespace ZeroLevel.MsSql
{
public class SqlDbProvider :
IDbProvider
{
#region Fields
private readonly SqlDbConnectionFactory _factory;
private const int Timeout = 60000;
public string ConnectionString
{
get { return _factory.ConnectionString; }
}
public string Server
{
get { return _factory.Server; }
}
public string Base
{
get { return _factory.Base; }
}
#endregion
#region .Ctor
/// <summary>
/// Конструктор.
/// </summary>
public SqlDbProvider(SqlDbConnectionFactory factory)
{
_factory = factory;
}
#endregion
#region ExecuteNonResult
public void ExecuteNonResult(IEnumerable<ZSqlCommand> commands)
{
using (DbConnection connection = _factory.CreateConnection())
{
foreach (var zcmd in commands)
{
using (var cmd = CreateCommand(connection, zcmd.Query, zcmd.Parameters, Timeout))
{
cmd.ExecuteNonQuery();
}
}
connection.Close();
}
}
public int ExecuteNonResult(string query)
{
return ExecuteNonResult(query, null);
}
public int ExecuteNonResult(string query, DbParameter[] par)
{
using (DbConnection connection = _factory.CreateConnection())
{
try
{
using (var cmd = CreateCommand(connection, query, par, Timeout))
{
return cmd.ExecuteNonQuery();
}
}
finally
{
connection.Close();
}
}
}
public T Insert<T>(string insert_query, SqlParameter[] par)
{
DbConnection connection = _factory.CreateConnection();
try
{
using (var cmd = CreateCommand(connection, insert_query, par, Timeout))
{
var result = cmd.ExecuteScalar();
return (T)result;
}
}
finally
{
connection.Close();
connection.Dispose();
}
}
#endregion
#region ExecuteQueryDataTable
public DataTable ExecuteQueryDataTable(string query)
{
var ds = ExecuteQuerySqlDataSet(query);
if (ds != null && ds.Tables.Count > 0)
{
return ds.Tables[0];
}
return null;
}
public DataTable ExecuteQueryDataTable(string query, DbParameter[] par)
{
var ds = ExecuteQuerySqlDataSet(query, par);
if (ds != null && ds.Tables.Count > 0)
{
return ds.Tables[0];
}
return null;
}
#endregion
#region ExecuteQuerySqlDataSet
public DataSet ExecuteQuerySqlDataSet(string query)
{
var ds = new DataSet("DataSet");
using (var connection = _factory.CreateConnection())
{
using (var cmd = CreateCommand(connection, query, null, Timeout))
{
using (var da = new SqlDataAdapter(cmd))
{
da.Fill(ds);
}
}
connection.Close();
}
return ds;
}
public DataSet ExecuteQuerySqlDataSet(string query, DbParameter[] par)
{
var ds = new DataSet("DataSet");
using (var connection = _factory.CreateConnection())
{
using (var cmd = CreateCommand(connection, query, par, Timeout))
{
using (var da = new SqlDataAdapter(cmd))
{
da.Fill(ds);
}
}
connection.Close();
}
return ds;
}
#endregion
#region ExecuteScalar
public object ExecuteScalar(string query)
{
using (var connection = _factory.CreateConnection())
{
try
{
using (var cmd = CreateCommand(connection, query, null, Timeout))
{
return cmd.ExecuteScalar();
}
}
finally
{
connection.Close();
}
}
}
public object ExecuteScalar(string query, DbParameter[] par)
{
using (var connection = _factory.CreateConnection())
{
try
{
using (var cmd = CreateCommand(connection, query, par, Timeout))
{
return cmd.ExecuteScalar();
}
}
finally
{
connection.Close();
}
}
}
#endregion
#region ExecuteStoredProcedure
public int ExecProcedure(string name)
{
using (var connection = _factory.CreateConnection())
{
try
{
using (var command = new SqlCommand(name, connection)
{
CommandType = CommandType.StoredProcedure
})
{
command.CommandTimeout = 300000;
return command.ExecuteNonQuery();
}
}
finally
{
connection.Close();
}
}
}
#endregion
public DbReader ExecuteReader(string query, DbParameter[] par)
{
var connection = _factory.CreateConnection();
return new DbReader(connection, CreateCommand(connection, query, par, Timeout));
}
#region LazySelect
public void LazySelect(string query, DbParameter[] par, Func<DbDataReader, bool> readHandler)
=> LazySelect(query, par, readHandler, Timeout);
public void LazySelect(string query, DbParameter[] par, Func<DbDataReader, bool> readHandler, int timeout = Timeout)
{
using (var connection = _factory.CreateConnection())
{
using (var cmd = CreateCommand(connection, query, par, Timeout))
{
using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
try
{
while (reader.Read())
{
if (false == readHandler(reader))
break;
}
}
catch (Exception ex)
{
Log.Error(ex, "Error executing query {0}.", cmd.CommandText);
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
}
}
public void LazySelectWithParameters(string query, IEnumerable<KeyValuePair<string, object>> par, Func<DbDataReader, bool> readHandler, int timeout = Timeout)
{
using (var connection = _factory.CreateConnection())
{
using (var cmd = CreateCommand(connection, query, null, Timeout))
{
if (par != null && par.Any())
{
foreach (var p in par)
{
cmd.Parameters.AddWithValue(p.Key, p.Value);
}
}
using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
try
{
while (reader.Read())
{
if (false == readHandler(reader))
break;
}
}
catch (Exception ex)
{
Log.Error(ex, "Error executing query {0}.", cmd.CommandText);
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
}
}
#endregion
#region ExistsTable
private const string QueryExistsTable = @"IF OBJECT_ID (N'[{0}]', N'U') IS NOT NULL SELECT 1 AS res ELSE SELECT 0 AS res";
public bool ExistsTable(string tableName)
{
return Convert.ToInt32(ExecuteScalar(String.Format(QueryExistsTable, tableName))) == 1;
}
#endregion
#region Commands
private static SqlParameter[] ProcessParameters(DbParameter[] par)
{
if (par != null)
{
var result = new SqlParameter[par.Length];
for (int i = 0; i < par.Length; i++)
{
if (par[i] is SqlParameter)
{
result[i] = (SqlParameter)par[i];
}
else
{
result[i] = new SqlParameter(par[i].ParameterName,
par[i].Value ?? DBNull.Value);
result[i].Size = par[i].Size;
}
}
return result;
}
return new SqlParameter[0];
}
public static SqlCommand CreateCommand(DbConnection connection, string query, DbParameter[] parameters, int timeout)
{
var command = connection.CreateCommand();
command.CommandText = query;
command.CommandType = CommandType.Text;
if (timeout > 0)
command.CommandTimeout = timeout;
if (parameters != null && parameters.Length > 0)
command.Parameters.AddRange(ProcessParameters(parameters));
return (SqlCommand)command;
}
#endregion
#region SQL Server execute plan reset
private const string CLEAN_PLAN_CACHEE_QUERY = "DBCC FREEPROCCACHE WITH NO_INFOMSGS;";
/// <summary>
/// Выполняет удаление всех элементов из кэша планов.
/// Применимо для ускорения работы SQL Server, при очистке кэша создаются новые планы
/// исполнения для новых значений запросов.
/// </summary>
public void CleanPlanCachee()
{
using (var connection = _factory.CreateConnection())
{
using (var cmd = CreateCommand(connection, CLEAN_PLAN_CACHEE_QUERY,
null, Timeout))
{
cmd.ExecuteNonQuery();
}
}
}
#endregion
#region Static methods
/// <summary>
/// Создает базу данных
/// </summary>
/// <param name="server">Сервер</param>
/// <param name="database">Название базы данных</param>
public static void CreateDatabase(string server, string database, string login, string password)
{
if (string.IsNullOrEmpty(server))
{
throw new ArgumentException("Не указано имя сервера");
}
if (string.IsNullOrEmpty(database))
{
throw new ArgumentException("Не указано имя базы данных");
}
using (var connection = new SqlConnection(SqlDbConnectionFactory.BuildConnectionString(server, "master", login, password)))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = String.Format("CREATE DATABASE {0}", database);
command.ExecuteNonQuery();
}
}
}
/// <summary>
/// Выполняет проверку существования базы данных с указанным именем
/// </summary>
public static bool CheckDatabaseExists(string serverName, string databaseName)
{
string sqlExistsDBQuery;
bool result = false;
try
{
using (var tmpConn = new SqlConnection(String.Format("server={0};Trusted_Connection=yes", serverName)))
{
tmpConn.Open();
sqlExistsDBQuery = string.Format("SELECT database_id FROM sys.databases WHERE Name = '{0}'", databaseName);
using (SqlCommand sqlCmd = new SqlCommand(sqlExistsDBQuery, tmpConn))
{
object resultObj = sqlCmd.ExecuteScalar();
int databaseID = 0;
if (resultObj != null)
{
int.TryParse(resultObj.ToString(), out databaseID);
}
result = (databaseID > 0);
}
}
}
catch (Exception ex)
{
Log.Error(ex, "Сбой при попытке подключения к серверу {0} и проверке наличия базы данных {1}",
serverName, databaseName);
result = false;
}
return result;
}
/// <summary>
/// Удаляет базу данных
/// </summary>
public static void DropDatabase(string server, string database, string login, string password)
{
if (string.IsNullOrEmpty(server))
{
throw new ArgumentException("Не указано имя сервера");
}
if (string.IsNullOrEmpty(database))
{
throw new ArgumentException("Не указано имя базы данных");
}
using (var connection = new SqlConnection(SqlDbConnectionFactory.BuildConnectionString(server, "master", login, password)))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = String.Format("ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;\r\nDROP DATABASE [{1}]", database, database);
command.ExecuteNonQuery();
}
}
}
#endregion
}
}

Powered by TurnKey Linux.