[英]Generic function for reading data from SQL Server
可以說我有兩個看起來像這樣的課程。
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 char限制。
我不認為你會買太多試圖將這個泛化。 在創建Foo1
和Foo2
的過程之間真正常見的唯一部分是創建/關閉Connection
和DataReader
。 它們將在DataReader
和類之間具有不同的SQL命令和不同的映射。
我的建議是使用像NHibernate這樣的庫或已經抽象掉數據庫垃圾的實體框架,或者抽象掉這些部分並讓工廠從DataReader
創建Foo1
和Foo2
實例。 否則,您將最終得到一堆開關,這些開關根據您嘗試創建的對象類型(這是您要走的路)改變代碼,或使用反射自動將屬性映射到數據庫列。
不幸的是,我不是專家,但我想我得到了你想做的事。 我的建議(雖然它可能不是最好的)是創建一個數據類型的枚舉,然后在泛型函數中搜索它的提交,然后你可以對你輸入的字符串使用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的地方,左邊幾乎是字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.