簡體   English   中英

基於SQL中的一對多表關系填充對象

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM