여러 출력으로 여러 쿼리 배치

c# dapper generics refactoring sql

문제

나는이 클래스를 가지고 있는데, 그 클래스에서 나는 다음과 같은 것을하기 위해

var results = SqlWrapper.ExecuteQuery<Product,Customer>("SELECT id FROM Products; SELECT id FROM Customers;");

어디에

results[0] = List<Product>
results[1] = List<Customer>

나는 1,2,3 개의 출력 객체를 지원하지만 임의로하고 싶습니다. 클래스는 또한 추악하고 복사 및 붙여 넣기 코드로 가득차 있습니다. 선택적으로 연결을 전달하여 연결을 재사용하고 싶지만 코드가 부정한 것처럼 보이는 경우를 고려해야합니다. 내가 진정으로 원하는 것은 params T[] 를 정의하는 방법이지만, 그 doesnt 작업을 이해합니다. 이 코드는 어떤 방식 으로든 청소 / 단축 될 수 있습니까?

using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using Dapper;

namespace SqlWrapper
{
    public static class SqlWrapper
    {
        private const string SqlConnectionString = "Server=localhost;Database=TTDS;User Id=sa;Password=sa;";


        public static List<T> ExecuteQuery<T>(string sql, object param = null, SqlConnection sqlConnection = null)
        {
            if (sqlConnection != null)
            {
                return sqlConnection.Query<T>(sql, param).ToList();
            }

            using (var tempSqlConnection = new SqlConnection(SqlConnectionString))
            {
                tempSqlConnection.Open();
                return tempSqlConnection.Query<T>(sql, param).ToList();
            }
        }


        public static List<dynamic> ExecuteQuery<T1, T2>(string sql, object param = null, SqlConnection sqlConnection = null)
        {
            if (sqlConnection != null)
            {
                return MultiQuery<T1, T2>(sqlConnection, sql, param);
            }

            using (var tempSqlConnection = new SqlConnection(SqlConnectionString))
            {
                return MultiQuery<T1, T2>(tempSqlConnection, sql, param);
            }
        }

        public static List<dynamic> ExecuteQuery<T1, T2, T3>(string sql, object param = null,
            SqlConnection sqlConnection = null)
        {
            if (sqlConnection != null)
            {
                return MultiQuery<T1, T2, T3>(sqlConnection, sql, param);
            }

            using (var tempSqlConnection = new SqlConnection(SqlConnectionString))
            {
                return MultiQuery<T1, T2, T3>(tempSqlConnection, sql, param);
            }
        }

        private static List<dynamic> MultiQuery<T1, T2>(SqlConnection sqlConnection, string sql, object param = null)
        {
            var rv = new List<dynamic>();

            using (var grid = sqlConnection.QueryMultiple(sql, param))
            {
                rv.Add(grid.Read<T1>().ToList());
                rv.Add(grid.Read<T2>().ToList());
            }

            return rv;
        }

        private static List<dynamic> MultiQuery<T1, T2, T3>(SqlConnection sqlConnection, string sql, object param = null)
        {
            var rv = new List<dynamic>();

            using (var grid = sqlConnection.QueryMultiple(sql, param))
            {
                rv.Add(grid.Read<T1>().ToList());
                rv.Add(grid.Read<T2>().ToList());
                rv.Add(grid.Read<T3>().ToList());
            }

            return rv;
        }


        public static void ExecuteNonQuery(SqlConnection sqlConnection, string sql, object param, int? timeout = null)
        {
            if (sqlConnection != null)
            {
                sqlConnection.Execute(sql, param, commandTimeout: timeout);
            }
            else
            {
                using (var tempSqlConnection = new SqlConnection(SqlConnectionString))
                {
                    tempSqlConnection.Open();
                    tempSqlConnection.Execute(sql, param, commandTimeout: timeout);
                }
            }
        }
    }
}

수락 된 답변

내가 가지고있는 몇 가지 아이디어를 보여주는 몇 가지 테스트되지 않은 코드가 있습니다.

  1. "using"은 매우 멋지지만 선택적으로 연결을 먼저 작성한 다음 필요에 따라 finally 블록에 sqlConnection을 배치하면 코드를 줄일 수 있습니다.
  2. Tuple<List<T>,List<U>,List<V>> 를 반환하면 쉽게 사용할 수있는 강력한 반환 값을 가질 수 있습니다
  3. 복잡하지 않은 함수에서 가장 복잡한 함수를 호출하면 중복 된 코드를 최소화 할 수 있습니다.

public static class SqlWrapper
{
    private const string SqlConnectionString = "Server=localhost;Database=TTDS;User Id=sa;Password=sa;";

    private class NoResult { }

    public static List<T1> ExecuteQuery<T1>(string sql, object param = null, SqlConnection sqlConnection = null)
    {
        return ExecuteQuery<T1, NoResult, NoResult>(sql, param, sqlConnection).Item1;
    }

    public static Tuple<List<T1>, List<T2>> ExecuteQuery<T1, T2>(string sql, object param = null, SqlConnection sqlConnection = null)
    {
        var result = ExecuteQuery<T1, T2, NoResult>(sql, param, sqlConnection);
        return Tuple.Create(result.Item1, result.Item2);
    }

    public static Tuple<List<T1>, List<T2>, List<T3>> ExecuteQuery<T1, T2, T3>(string sql, object param = null, SqlConnection sqlConnection = null)
    {
        List<T1> list1;
        List<T2> list2 = null;
        List<T3> list3 = null;
        bool needsDisposed = false;

        if (sqlConnection == null)
        {
            sqlConnection = new SqlConnection(SqlConnectionString);
            sqlConnection.Open();
            needsDisposed = true;
        }

        try
        {
            using (var grid = sqlConnection.QueryMultiple(sql, param))
            {
                list1 = grid.Read<T1>().ToList();
                if (typeof(T2) != typeof(NoResult))
                {
                    list2 = grid.Read<T2>().ToList();
                }
                if (typeof(T3) != typeof(NoResult))
                {
                    list3 = grid.Read<T3>().ToList();
                }

                return Tuple.Create(list1, list2, list3);
            }
        }
        finally { if (needsDisposed) sqlConnection.Dispose(); }
    }


    public static void ExecuteNonQuery(SqlConnection sqlConnection, string sql, object param, int? timeout = null)
    {
        bool needsDisposed = false;

        if (sqlConnection == null)
        {
            sqlConnection = new SqlConnection(SqlConnectionString);
            sqlConnection.Open();
            needsDisposed = true;
        }

        try { sqlConnection.Execute(sql, param, commandTimeout: timeout); }
        finally { if (needsDisposed) sqlConnection.Dispose(); }
    }
}


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.