清洁设计以处理来自IDataReader的多个结果集

时间:2011-12-02 15:28:28

标签: c# .net design-patterns c#-4.0

也许SO不是这个地方,如果不是,我道歉,但我不禁想到有更好的方法来做到这一点。这似乎是一种粗略而不是非常干净的方法,可以检查我所处的结果集,然后执行相应的操作。有人有什么建议吗? (请忽略我总是返回null的事实。)

public MemberDto Load(long entityId)
    {
        using (var cn = new SqlConnection(@"connectionstringstuff"))
        {
            cn.Open();
            using (SqlCommand cm = cn.CreateCommand())
            {
                cm.CommandText = "Client.[MemberGet]";
                cm.CommandType = CommandType.StoredProcedure;

                cm.Parameters.AddWithValue("@EntityId", entityId);

                using (IDataReader dr = cm.ExecuteReader())
                {
                    var memberModel = new MemberDto();
                    do
                    {
                        while (dr.Read())
                        {
                            var sdr = new SafeDataReader(dr);
                            var firstColumn = sdr.GetName(0);
                            if (firstColumn.StartsWith("Attribute"))
                            {
                                AddAttribute(memberModel, sdr);
                            }
                            else if (firstColumn.StartsWith("AlternateId"))
                            {
                                AddAlternateId(memberModel, sdr);
                            }
                            else
                            {
                                memberModel.ClientId = sdr.GetInt64("ClientId");
                                memberModel.Id = sdr.GetInt64("EntityId");
                                memberModel.Name = sdr.GetString("EntityName");
                            }
                        }
                    } while (dr.NextResult());
                }
            }
        }

        return null;
    }

    private void AddAttribute(MemberDto model, SafeDataReader reader)
    {
        model.Attributes.Add(
            reader.GetInt32("AttributeTypeId").As<EntityAttributeType>(),
            reader.GetString("Value"));
    }

    private void AddAlternateId(MemberDto model, SafeDataReader reader)
    {
        model.Attributes.Add(
            reader.GetInt32("AlternateIdTypeId").As<EntityAttributeType>(),
            reader.GetString("Value"));
    }

2 个答案:

答案 0 :(得分:0)

我们处理这个问题的方法不是循环使用nextresult,而是显式编码以匹配底层数据。这种方法的预期结果在某种程度上更加明显(当然,我认为)。

这是一个重写示例,假设顺序是成员模型,属性和替代。

    while (dr.Read())
    {
        var sdr = new SafeDataReader(dr);
        memberModel.ClientId = sdr.GetInt64("ClientId");
        memberModel.Id = sdr.GetInt64("EntityId");
        memberModel.Name = sdr.GetString("EntityName");
    }
    if (dr.NextResult())
    {
        while (dr.Read())
        {
            AddAttribute(memberModel, new SafeDataReader(dr));
        }
    }
    if (dr.NextResult())
    {
        while (dr.Read())
        {
            AddAlternateId(memberModel, new SafeDataReader(dr));
        }
    }

答案 1 :(得分:0)

也许所有返回多个结果集的sp应始终首先包含一个结果集,指定以哪种顺序返回哪些结果集:

dr = multRsCmd.ExecureReader();

// first rs is always the meta
List<string> resultSetIds = new List<string>();
while (dr.Read())
   resultSetIds.Add(dr[0]

foreach (string rsId in resultSetIds)
{

   if (!dr.NextResult())
      break; // or throw, should not happen

   if (rsId == "ClientDataWithAttribute")
   {
      // code to handle the exact rs layout for ClientDataWithAttribute
      //
      //
   }
   else if (rsId == "ClientDataWithAltId")
   {
      // code to handle the exact rs layout for ClientDataWithAltId
      //
      //   
   }
   else if (rsId == "ClientData")
   {
      // code to handle the exact rs layout for ClientData
      //
      //   
   }

}

这当然是为重构而尖叫:

dr = multRsCmd.ExecureReader();

// first rs is always the meta
List<string> resultSetIds = new List<string>();
while (dr.Read())
   resultSetIds.Add(dr[0]

foreach (string rsId in resultSetIds)
{

   if (!dr.NextResult())
      break; // or throw, should not happen

   // pull subclass out of registry of readers
   ResultSetReader rsr = ResultSetReaders.Find(rsId);

   // subclass cleanly holds the layout-dependent logic
   memberModel = rsr.FromDataReader(dr);

 }

看起来很干净,但你甚至可以在ResultSetReader中添加默认行为来驱动配置文件或其他来源的DTO属性映射,并且只有在你获得特殊条件时才会覆盖。你明白了。