[英]Populating an object based on a one-to-many table relationship in SQL
我在C#中有一個像這樣的對象:
private ClassWidget
{
public int ID;
public List<int> WidgetFavoriteNumbers;
}
假設我在SQL中有兩個表,一個定義小部件屬性,另一個包含單個小部件的許多記錄,讓我們說小部件最喜歡的數字:
widgets
-----------
id (int, not null)
// other properties ...
widget_nums
----------
widget_id (int, not null)
num (int)
我發現自己經常執行兩個SQL查詢來填充此對象,即使我知道我可以加入表來創建一個查詢。 原因是,僅使用我需要的數據填充對象似乎更簡單,而不是迭代具有大量重復數據的結果集。 當然,與真實場景相比,這個小部件示例更加簡化。 這是一個例子:
int WidgetID = 8;
ClassWidget MyWidget = new ClassWidget();
using (SqlConnection conn = GetSQLConnection())
{
using (SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = @"SELECT id FROM widgets WHERE id = @WidgetID;";
cmd.Parameters.AddWithValue("WidgetID", WidgetID);
using (SqlDataReader Reader = cmd.ExecuteReader())
{
if (Reader.HasRows)
MyWidget.ID = GetDBInt("id", Reader); // custom method to read database result
}
cmd.CommandText = @"SELECT num FROM widget_nums WHERE widget_id = @WidgetID;";
using (SqlDataReader Reader = cmd.ExecuteReader())
{
if (Reader.HasRows)
while (Reader.Read())
MyWidget.WidgetFavoriteNumbers.Add(GetDBInt("num", Reader));
}
conn.Close();
}
}
我的問題是我是否應該繼續使用這種方法,或者是否建議執行表連接。 如果建議使用表連接,那么填充對象的最佳設計模式是什么? 我的問題是我必須創建一些邏輯來過濾掉重復的行,當我得到所有小部件而不是一個小部件時,這個特別復雜。
我會使用表連接。 創建一個遍歷結果的方法非常簡單。 即使在查詢多個小部件及其widget_nums時,也可以使用此方法
private IEnumerable<ClassWidget> MapReaderToWidget(IDataReader reader) {
var dict = new Dictionary<int, ClassWidget>();
while (reader.Read()) {
var id = (int)reader["id"];
ClassWidget widget;
if (!dict.TryGetValue(id, out widget)) {
widget = new ClassWidget {
ID = id,
WidgetFavoriteNumbers = new List<int>();
};
dict.Add(id, widget);
}
widget.WidgetFavoriteNumbers.Add((int)reader["num"]);
}
return dict.Values;
}
然后重寫您的方法如下:
using (SqlConnection conn = GetSQLConnection())
{
using (SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = @"SELECT id FROM widgets INNER JOIN widget_nums on .... WHERE id = @WidgetID;";
cmd.Parameters.AddWithValue("WidgetID", WidgetID);
using (SqlDataReader Reader = cmd.ExecuteReader()) {
return MapReaderToWidget(reader).FirstOrDefault();
}
}
}
使用表連接。 它使用單個SQL查詢,並且速度非常快(遠遠快於您當前的方法)。 對於過濾掉重復行的邏輯,你可以想出一個查詢,我想; 花一些時間來開發一個查詢,為您提供數據庫中的所需內容,您會對結果感到滿意。
我認為您應該開始轉向Ado Entity Framework或LinQ to SQL作為數據提供者,因為它將為您節省大量時間,並且它將以有效的方式完成您想要的任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.