基于SQL中的一对多表关系填充对象

我在C#中有一个像这样的对象:

private ClassWidget { public int ID; public List 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 MapReaderToWidget(IDataReader reader) { var dict = new Dictionary(); while (reader.Read()) { var id = (int)reader["id"]; ClassWidget widget; if (!dict.TryGetValue(id, out widget)) { widget = new ClassWidget { ID = id, WidgetFavoriteNumbers = new List(); }; 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作为数据提供者,因为它将为您节省大量时间,并且它将以有效的方式完成您想要的操作。