存储过程的通用数据访问代码返回Ienumerable <t>?</t>

时间:2014-05-25 17:44:19

标签: c# stored-procedures ado.net refactoring

我希望使其更具通用性和可重用性,而不是使用不同的Enumerable重复相同的ADO.net代码。

我有以下ADO.Net代码来返回对象集合:

public static IEnumerable<TasCriteria> GetTasCriterias()
    {
        using (var conn = new SqlConnection(_connectionString))
        {
            var com = new SqlCommand();
            com.Connection = conn;
            com.CommandType = CommandType.StoredProcedure;

            com.CommandText = "IVOOARINVENTORY_GET_TASCRITERIA";
            var adapt = new SqlDataAdapter();
            adapt.SelectCommand = com;
            var dataset = new DataSet();
            adapt.Fill(dataset);

            var types = (from c in dataset.Tables[0].AsEnumerable()
                         select new TasCriteria()
                         {
                              TasCriteriaId = Convert.ToInt32(c["TasCriteriaId"]),
                              TasCriteriaDesc= c["CriteriaDesc"].ToString()
                         }).ToList<TasCriteria>();

            return types;
        }

    }

型号:

 public class TasCriteria
    {
        public int TasCriteriaId { get; set; }
        public string TasCriteriaDesc { get; set; }
    }

2 个答案:

答案 0 :(得分:1)

如果存储过程返回的列名与您的类中的属性完全匹配,则可以使用此代码之类的反射。我将做一个练习,为其他人添加存储过程的参数。 (顺便说一句,这是未经测试的代码,我把它写在了我的头顶)

    public static IEnumerable<T> GetStoredProcedure<T>(string procedure) where T : new()
    {
        var data = new List<T>();

        using (var conn = new SqlConnection(_connectionString))
        {
            var com = new SqlCommand();
            com.Connection = conn;
            com.CommandType = CommandType.StoredProcedure;

            com.CommandText = procedure;
            var adapt = new SqlDataAdapter();
            adapt.SelectCommand = com;
            var dataset = new DataSet();
            adapt.Fill(dataset);

            //Get each row in the datatable
            foreach (DataRow row in dataset.Tables[0].Rows)
            {
                //Create a new instance of the specified class
                var newT = new T();

                //Iterate each column
                foreach (DataColumn col in dataset.Tables[0].Columns)
                {
                    //Get the property to set
                    var property = newT.GetType().GetProperty(col.ColumnName);
                    //Set the value
                    property.SetValue(newT, row[col.ColumnName]);
                }

                //Add it to the list
                data.Add(newT);
            }

            return data;
        }

    }

所以假设你有一个这样的课:

public class TasCriteria
{
    public int TasCriteriaId { get; set; }
    public string TasCriteriaDesc { get; set; }
}

您可以像这样调用函数:

IEnumerable<TasCriteria> criteria = GetStoredProcedure<TasCriteria>("IVOOARINVENTORY_GET_TASCRITERIA");

答案 1 :(得分:0)

选项是在主方法之外提取您的特定代码。

例如:

public static IEnumerable<T> GetCriterias(
                            string storedProcedureName,
                            Func<IEnumerable<T>> enumerateMethod)
{
    using (var conn = new SqlConnection(_connectionString))
    {
        var com = new SqlCommand();
        com.Connection = conn;
        com.CommandType = CommandType.StoredProcedure;

        com.CommandText = storedProcedureName;
        var adapt = new SqlDataAdapter();
        adapt.SelectCommand = com;
        var dataset = new DataSet();
        adapt.Fill(dataset);

        return enumerateMethod(dataset.Tables[0]);
    }
}

如果存储过程需要参数,则可以将函数重载为:

public static IEnumerable<T> GetCriterias(
                        string storedProcedureName,
                        Func<IEnumerable<T>> enumerateMethod,
                        SqlParameter[] parameters)

使用此代码,您可以定义与de Func<>签名匹配的方法。

public static IEnumerable<TasCriteria> EnumerateTasCriteria(DataTable table)
{
    return 
        (from c in table.AsEnumerable()
        select new TasCriteria()
        {
            TasCriteriaId = Convert.ToInt32(c["TasCriteriaId"]),
            TasCriteriaDesc= c["CriteriaDesc"].ToString()
        }).ToList<TasCriteria>();
}

public static IEnumerable<DetailCriteria> EnumerateDetailCriteriaCriteria(
                                            DataTable table)
{
    return 
        (from c in table.AsEnumerable()
         select new DetailCriteria()
        {
        DetailCriteriaId = Convert.ToInt32(c["DetailCriteriaId"]),
        DetailCriteriaDesc = c["CriteriaDesc"].ToString()
        }).ToList<TasCriteria>();
}

然后,您可以将代码称为:

IEnumerable<TasCriteria> task = 
         GetCriterias<TasCriteria>("IVOOARINVENTORY_GET_TASCRITERIA", EnumerateTasCriteria);
IEnumerable<DetailCriteria> details =
         GetCriterias<DetailCriteria>("IVOOARINVENTORY_GET_DETAILSCRITERIA", EnumerateDetailCriteriaCriteria);