Чистый дизайн для обработки нескольких наборов результатов из IDataReader - PullRequest
0 голосов
/ 02 декабря 2011

Может быть, ТАК не место для этого, и я прошу прощения, если это не так, но я не могу не думать, что есть лучший способ сделать это. Это просто грубый и не очень чистый способ проверить, какой набор результатов у меня включен, и затем выполнить соответствующее действие. У кого-нибудь есть предложения? (Пожалуйста, игнорируйте тот факт, что я всегда возвращаю ноль).

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 голосов
/ 03 декабря 2011

Возможно, все 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 из файла конфигурации или другого источника и переопределять его только при получении специальных условий.Вы поняли.

0 голосов
/ 02 декабря 2011

Способ, которым мы подходим к этому, заключается не в том, чтобы зацикливаться на следующем результате, а в явном кодировании его для соответствия базовым данным. Несколько более визуально очевидно, каковы ожидаемые результаты с этим подходом (на мой взгляд, конечно).

Вот пример переписывания, при условии, что порядок - это membermodel, атрибуты и альтернативы.

    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));
        }
    }
...