tvolodimir
9/13/2013 - 12:50 PM

Generic sql procedure executor C#

Generic sql procedure executor C#

public class GenericSqlProvider
{
    private readonly string connectionString;

    public GenericSqlProvider(string connectionString)
    {
        this.connectionString = connectionString;
    }

    public IResult<ProcedureResult> ExecuteCall(string procedureName, IDictionary<string, object> input)
    {
        using (var connection = new SqlConnection(connectionString))
        {
            var command = new SqlCommand(procedureName, connection) { CommandType = CommandType.StoredProcedure };

            var parameters = input.Select(p =>
            {
                var param = command.CreateParameter();
                param.ParameterName = p.Key;
                param.Value = p.Value;
                return param;
            }).ToArray();


            SqlParameter sampParm = command.Parameters.Add("RETURN_VALUE", SqlDbType.Int);
            sampParm.Direction = ParameterDirection.ReturnValue;

            command.Parameters.AddRange(parameters);

            try
            {
                connection.Open();
                var reader = command.ExecuteReader();

                /*var tables = new List<DataTable>();

                while (!reader.IsClosed)
                {
                    DataTable schemaTable = reader.GetSchemaTable();

                    foreach (DataRow row in schemaTable.Rows)
                    {
                        foreach (DataColumn column in schemaTable.Columns)
                        {
                            Console.WriteLine("{0} = {1}", column.ColumnName, row[column]);
                        }
                    }
                    Console.WriteLine("\n");
                    var table = new DataTable();
                    table.Load(reader);
                    tables.Add(table);

                    foreach (DataRow row in table.Rows)
                    {
                        foreach (DataColumn column in table.Columns)
                        {
                            Console.WriteLine("{0} = {1}", column.ColumnName, row[column]);
                        }
                    }
                    Console.WriteLine("\n");
                }*/

                var results = new List<ICollection<DataRowObject>>();

                if (reader.HasRows)
                {
                    var dataObj = new List<DataRowObject>();
                    while (reader.Read())
                    {
                        var dataRow = new DataRowObject();
                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            dataRow.Add(reader.GetName(i), reader[i]);
                        }
                        dataObj.Add(dataRow);
                    }
                    results.Add(dataObj);
                }
                else
                {
                    results.Add(null);
                }


                while (reader.NextResult())
                {
                    if (reader.HasRows)
                    {
                        var dataObj = new List<DataRowObject>();
                        while (reader.Read())
                        {
                            var dataRow = new DataRowObject();
                            for (int i = 0; i < reader.FieldCount; i++)
                            {
                                dataRow.Add(reader.GetName(i), reader[i]);
                            }
                            dataObj.Add(dataRow);
                        }
                        results.Add(dataObj);
                    }
                    else
                    {
                        results.Add(null);
                    }
                }

                var returnValue = 0;
                try
                {
                    returnValue = (int)command.Parameters["RETURN_VALUE"].Value;
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch { }
                // ReSharper restore EmptyGeneralCatchClause

                return new Result<ProcedureResult>(new ProcedureResult(results.Count == 1 && results[0] == null ? null : results, returnValue));
            }
            catch (Exception ex)
            {
                return new Result<ProcedureResult>(null, (int)ExceptionType.DB_TIMEOUT, ex.Message);
            }
            finally
            {
                connection.Close();
            }
        }
    }
}

public class ProcedureResult
{
    public IEnumerable<IEnumerable<DataRowObject>> Results { get; private set; }
    public int ReturnValue { get; private set; }

    public ProcedureResult(IEnumerable<IEnumerable<DataRowObject>> results, int returnValue = 0)
    {
        Results = results == null ? null : results.Cast<List<DataRowObject>>().ToList();
        ReturnValue = returnValue;
    }
}

public class DataRowObject : NameObjectCollectionBase
{
    public void Add(string key, object value)
    {
        BaseAdd(key, value);
    }

    public KeyValuePair<string, object> this[int index]
    {
        get { return new KeyValuePair<string, object>(BaseGetKey(index), BaseGet(index)); }
    }

    public object this[string key] { get { return BaseGet(key); } }

    public override System.Collections.IEnumerator GetEnumerator()
    {
        for (int i = 0; i < Count; i++)
        {
            yield return this[i];
        }
    }
}

public interface IResult
{
    bool Success { get; }
    string ErrorMessage { get; }
    int ErrorCode { get; }
}

public class Result : IResult
{
    public bool Success { get; private set; }
    public string ErrorMessage { get; private set; }
    public int ErrorCode { get; private set; }

    public Result(int errorCode = 0, string errorMessage = "")
    {
        ErrorCode = errorCode;
        ErrorMessage = errorMessage;
        Success = (errorCode == 0) && string.IsNullOrEmpty(errorMessage);
    }

    public static Result Successful = new Result();

    public override string ToString()
    {
        return Success ? "Success" : string.Format("{0}({1})", ErrorCode, ErrorMessage);
    }
}

public interface IResult<out T> : IResult
{
    T Data { get; }
}

public class Result<TResult> : Result, IResult<TResult>
{
    public TResult Data { get; private set; }

    public Result(TResult data, int errorCode = 0, string errorMessage = "")
        : base(errorCode, errorMessage)
    {
        Data = data;
    }
}