用于从SQL Server读取数据的通用函数

时间:2013-02-15 23:02:21

标签: c# .net

假设我有两个看起来像这样的课程。

class Foo1
{
   public String P1 { get; set; }
   public String P2 { get; set; }
}

class Foo2
{
   public String P3 { get; set; }
   public String P4 { get; set; }
}

P1,P2,P3和P4 没有任何关系。与 Foo1 Foo2 相同。它们代表完全不同的对象。

我有两个数据库表,其中包含Foo1和Foo2对象的列表。我必须创建List<Foo1>List<Foo2>

返回Foo1和Foo2的存储过程的输入是不同的。

这是我的问题 - 我想创建一个通用函数,它将连接到数据库并按照我的意愿获取Foo1或Foo2列表

最初我想过这样的事情

internal static SqlDataReader GetData(String Proc,NameValueCollection InputParams,SqlConnection conn, ref String Err)
{

    using (SqlCommand cmd = conn.CreateCommand())
    {
        try
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = Proc;
            conn.Open();

            SqlCommandBuilder.DeriveParameters(cmd);


            foreach (SqlParameter p in cmd.Parameters)
            {
                if (p.Direction == ParameterDirection.Input)
                {

                    if (InputParams[p.ParameterName.ToLower().Substring(1)] != String.Empty)
                    {
                        p.Value = InputParams[p.ParameterName.ToLower().Substring(1)];
                        p.DbType = DbType.AnsiString;
                    }
                    else
                    {
                        Err += "<argumentnotfound>" + p.ParameterName + "</argumentnotfound>";                                    
                    }
                }
                else p.Value = DBNull.Value;

            }
            return cmd.ExecuteReader();
        }
        catch (Exception e)
        {
            return null;
        }       
    }   
} 

我不喜欢在此函数之外返回SqlDataReader或创建和关闭SqlConnection的想法。

理想情况下,我想在此函数中迭代“reader”对象,但返回List<Foo1>List<Foo2>。我能想到的一个解决方案就是这个

        internal static List<Object> GetData(NameValueCollection InputParams, ref String Err, String ClassName, String Proc)
{
    List<Object> [] objectlist = new List<Object>();
    using (SqlConnection conn = getConnection())
    {
        using (SqlCommand cmd = conn.CreateCommand())
        {
            try
            {
                /*
                    ~~ Same as before
                */
                SqlDataReader reader =  cmd.ExecuteReader();
                while(reader.Read())
                {

                    if(ClassName == "Foo1")
                    {
                        Foo1 f = new Foo1();
                        f.P1 = reader["p1"].ToString();
                        objectList.Add(f1);
                    }
                    else if(ClassName == "Foo2")
                    {
                        /* Create and initialize Foo2 object*/
                        objectList.Add(f2);
                    }


                }
                return objectList;
            }
            catch (Exception e)
            {

            }
            finally
            {
                conn.Close();
            }
        }
    }

    return null;
}

有更好/更优雅的方法吗?

修改

我忘了提到的是 - 我的最终目标是为来自Javascript的 AJAX 调用创建 JSON 。我的计划是迭代Foo1和Foo2对象列表,为每个请求创建Json数据。

我认为我可以在存储过程中创建JSON并将其作为varchar(max)返回,并使用JSON2.js在客户端创建JSOn对象。 我在这里看到的缺点是varchar限制为8000个字符。

2 个答案:

答案 0 :(得分:2)

我认为你不会想要购买太多试图将其泛化。创建Foo1Foo2的过程之间真正共同的唯一部分是创建/关闭ConnectionDataReader。它们将在DataReader和类之间具有不同的SQL命令和不同的映射。

我的建议是使用像NHibernate这样的库或已经抽象掉数据库垃圾的实体框架,或者抽象掉这些部分并让工厂从{创建Foo1Foo2实例{1}}。否则,您将最终得到一堆开关,这些开关根据您尝试创建的对象类型(这是您要走的路)改变代码,或使用反射自动将属性映射到数据库列。

答案 1 :(得分:0)

不幸的是,我不是专家,但我想我得到了你想做的事。我的建议(虽然它可能不是最好的)是创建一个数据类型的枚举,然后在泛型函数中搜索它的提交,然后你可以对你输入的字符串使用tablename。

我使用类似的方法来存储这种性质的信息,它看起来像这样......

功能:

    public UInt32 getKeyCode(string Key)
    {
        Constants.KeyboardControls keynum;
        if (Enum.TryParse<Constants.KeyboardControls>(Key, true, out keynum))
        {
            return (UInt32)(keynum);
        }
        else
        {
            return new UInt32();
        }
    }

枚举:

    public enum KeyboardControls : uint
    {
        F1 = 0x70,
        F2 = 0x71,
        F3 = 0x72,
        F4 = 0x73,
        F5 = 0x74,
        F6 = 0x75,
        F7 = 0x76,
        F8 = 0x77,
        F9 = 0x78,
        F10 = 0x79,
        F11 = 0x7A,
        F12 = 0x7B,
        left = 0x25,
        up = 0x26,
        right = 0x27,
        down = 0x28
    }

我希望这至少有一点帮助,你可以在枚举中列出任何对象,只需改变它对你的对象类型说的uint,左边几乎是字符串。