Правильный способ вернуть SQL DataRow для заполнения поля - PullRequest
1 голос
/ 22 июля 2011

У меня есть следующий сценарий, который я использовал, чтобы вернуть одну строку из базы данных SQL. После того, как я вернул данные, я просто использую их для заполнения полей в веб-форме.

Пример класса базы данных:

public class DBAccess
{
    public DataTable ReturnContactInfo(int userID)
    {
        // executes a stored procedure, populates a datatable, then returns it
    }
}

Пример использования класса для заполнения поля теоретического имени клиента:

protected void Page_Load(object sender, EventArgs e)
{
    if(!isPostBack)
    {
        DBAccess db = new DBAccess();
        DataTable dt =  db.ReturnContactInfo(1);
        if (dt.Rows.Count > 0)
        {
           customerName.Text = Convert.ToString(dt.Rows[0]["customerName"]);
        }
     }
}

Есть ли лучший или более эффективный способ сделать это («this» возвращает одну строку данных для извлечения данных)? Этот подход, безусловно, работает, но немного громоздко вводить dt.Rows [0] [string], когда я всегда и буду работать только со строкой с индексом 0. Пожалуйста, имейте в виду, что я хотел бы чтобы иметь возможность хранить все данные слоя данных, извлеченные в один класс. Что (из того, что я понимаю) означает, что я не могу использовать SqlDataReader, потому что он должен быть закрыт по окончании, чтобы я не мог вернуть его из своего класса уровня данных.

Ответы [ 3 ]

4 голосов
/ 22 июля 2011

Определите класс с членами, которые вы хотите в качестве свойств.Затем заполните и верните этот объект.Вы можете сделать это просто, используя такие инструменты, как «dapper»:

public Customer GetCustomer(int id)
{
     return connection.Query<Customer>("getCustomer",
         new {id}, // <=== param
         commandType: CommandType.StoredProcedure).Single();
}

Тогда:

var cust = GetCustomer(12345);
string name = cust.Name;

Сейчас:

  • ясно, что у нас есть одинobject
  • члены объекта очевидны и хорошо относятся к типу
  • вы избежите больших накладных расходов из DataTable
0 голосов
/ 22 июля 2011

Я написал генератор кода, который генерирует мой код доступа к данным, один класс на хранимую процедуру.Одним из вариантов является то, что вы можете указать, что его набор результатов состоит из одной строки.Использование простое: сгенерированный код вызывается с помощью метода-оболочки, который применяет любые ограничения, требуемые контрактом на использование, таким образом:

    public DataRow GetPatientData( int patientID )
    {
        dbo_GetPatientData67 sp = new dbo_GetPatientData( CONNECT_STRING_ID ) ;
        int                  rc = sp.Exec( patientID ) ;
        DataRow              dr = sp.ResultSet ;

        if ( dr == null ) throw new InvalidOperationException("nothing returned from stored procedure.") ;
        return dr ;
    }

Вот основные принципы кода доступа к данным:

/* generated code. do not change -- generated code */
public class dbo_GetPatientData
{

  public int     ReturnCode { get ; private set ; }
  public DataRow ResultSet { get ; private set ; }

  public int Exec(  int? @iPatientID )
  {
    using ( SqlConnection  conn = new SqlConnection( this._connectString ) )
    using ( SqlCommand     cmd  = conn.CreateCommand() )
    using ( SqlDataAdapter sda  = new SqlDataAdapter( cmd ) )
    {
      cmd.CommandText = STORED_PROCEDURE_NAME ;
      cmd.CommandType = CommandType.StoredProcedure ;

      //
      // 1. @iPatientID
      //
      // required
        SqlParameter p1 = new SqlParameter( @"@iPatientID" , SqlDbType.Int ) ;
        if ( @iPatientID == null )
        {
          p1.Value = System.DBNull.Value ;
        }
        else
        {
          p1.Value = @iPatientID ;
        }
        cmd.Parameters.Add( p1 ) ;

      // add return code parameter
      SqlParameter pReturnCode = new SqlParameter() ;
      pReturnCode.SqlDbType = System.Data.SqlDbType.Int ;
      pReturnCode.Direction = System.Data.ParameterDirection.ReturnValue ;
      cmd.Parameters.Add( pReturnCode ) ;

      DataSet ds = new DataSet() ;

      conn.Open() ;
      sda.Fill( ds ) ;
      conn.Close() ;

      DataTable dt    = ( ds.Tables.Count > 0 ? ds.Tables[0] : null ) ;
      this.ResultSet  = ( dt != null && dt.Rows.Count > 0 ? dt.Rows[0] : null ) ;
      this.ReturnCode = (int) pReturnCode.Value ;


    }

    return this.ReturnCode ;

  }

}

Теперь вам нужно иметь дело только с DataRow (хотя связанные с ним DataTable / DataSet и т. Д. Все еще существуют, если они вам нужны).Добавление методов расширения к классу DataRow устраняет изрядную утомительность понижения каждого столбца до правильного типа.Я бы лучше написал:

int? x = dr.CastAsIntNullable( "myColumn" ) ;

, чем обычный шаблон.

public static class DataRowExtensions
{

    #region downcast to DateTime

    public static DateTime CastAsDateTime( this DataRow row , int index )
    {
        return toDateTime( row[index] ) ;
    }
    public static DateTime CastAsDateTime( this DataRow row , string columnName )
    {
        return toDateTime( row[columnName] ) ;
    }

    public static DateTime? CastAsDateTimeNullable( this DataRow row , int index )
    {
        return toDateTimeNullable( row[index] );
    }
    public static DateTime? CastAsDateTimeNullable( this DataRow row , string columnName )
    {
        return toDateTimeNullable( row[columnName] ) ;
    }

    #region conversion helpers

    private static DateTime toDateTime( object o )
    {
        DateTime value = (DateTime)o;
        return value;
    }

    private static DateTime? toDateTimeNullable( object o )
    {
        bool  hasValue = !( o is DBNull );
        DateTime? value    = ( hasValue ? (DateTime?) o : (DateTime?) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to DateTime

    #region downcast to byte[]

    public static byte[] CastAsByteArray( this DataRow row , int index )
    {
        return toByteArray( row[index] );
    }
    public static byte[] CastAsByteArray( this DataRow row , string columnName )
    {
        return toByteArray( row[columnName] );
    }

    #region conversion helpers

    private static byte[] toByteArray( object o )
    {
        bool   hasValue = !( o is DBNull );
        byte[] value    = ( hasValue ? (byte[]) o : (byte[]) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to Byte[]

    #region downcast to int

    public static int CastAsInt( this DataRow row , int index )
    {
        return toInt( row[index] ) ;
    }
    public static int CastAsInt( this DataRow row , string columnName )
    {
        return toInt( row[columnName] ) ;
    }

    public static int? CastAsIntNullable( this DataRow row , int index )
    {
        return toIntNullable( row[index] );
    }
    public static int? CastAsIntNullable( this DataRow row , string columnName )
    {
        return toIntNullable( row[columnName] ) ;
    }

    #region conversion helpers

    private static int toInt( object o )
    {
        int value = (int)o;
        return value;
    }

    private static int? toIntNullable( object o )
    {
        bool hasValue = !( o is DBNull );
        int? value    = ( hasValue ? (int?) o : (int?) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to int

    #region downcast to decimal

    public static decimal CastAsDecimal( this DataRow row , int index )
    {
        return toDecimal( row[index] ) ;
    }
    public static decimal CastAsDecimal( this DataRow row , string columnName )
    {
        return toDecimal( row[columnName] ) ;
    }

    public static decimal? CastAsDecimalNullable( this DataRow row , int index )
    {
        return toDecimalNullable( row[index] );
    }
    public static decimal? CastAsDecimalNullable( this DataRow row , string columnName )
    {
        return toDecimalNullable( row[columnName] ) ;
    }

    #region conversion helpers

    private static decimal toDecimal( object o )
    {
        decimal value = (decimal)o;
        return value;
    }

    private static decimal? toDecimalNullable( object o )
    {
        bool     hasValue = !( o is DBNull );
        decimal? value    = ( hasValue ? (decimal?) o : (decimal?) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to decimal


    #region downcast to double

    public static double CastAsDouble( this DataRow row , int index )
    {
        return toDouble( row[index] ) ;
    }
    public static double CastAsDouble( this DataRow row , string columnName )
    {
        return toDouble( row[columnName] ) ;
    }

    public static double? CastAsDoubleNullable( this DataRow row , int index )
    {
        return toDoubleNullable( row[index] );
    }
    public static double? CastAsDoubleNullable( this DataRow row , string columnName )
    {
        return toDoubleNullable( row[columnName] ) ;
    }

    #region conversion helpers

    private static double toDouble( object o )
    {
        double value = (double)o;
        return value;
    }

    private static double? toDoubleNullable( object o )
    {
        bool     hasValue = !( o is DBNull );
        double? value    = ( hasValue ? (double?) o : (double?) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to double

    #region downcast to bool

    public static bool CastAsBool( this DataRow row , int index )
    {
        return toBool( row[index] ) ;
    }
    public static bool CastAsBool( this DataRow row , string columnName )
    {
        return toBool( row[columnName] ) ;
    }

    public static bool? CastAsBoolNullable( this DataRow row , int index )
    {
        return toBoolNullable( row[index] );
    }
    public static bool? CastAsBoolNullable( this DataRow row , string columnName )
    {
        return toBoolNullable( row[columnName] ) ;
    }

    #region conversion helpers

    private static bool toBool( object o )
    {
        bool value = (bool)o;
        return value;
    }

    private static bool? toBoolNullable( object o )
    {
        bool  hasValue = !( o is DBNull );
        bool? value    = ( hasValue ? (bool?) o : (bool?) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to bool

    #region downcast to string

    public static string CastAsString( this DataRow row , int index )
    {
        return toString( row[index] );
    }
    public static string CastAsString( this DataRow row , string columnName )
    {
        return toString( row[columnName] );
    }

    #region conversion helpers

    private static string toString( object o )
    {
        bool   hasValue = !( o is DBNull );
        string value    = ( hasValue ? (string) o : (string) null ) ;
        return value;
    }

    #endregion

    #endregion downcast to string

}
0 голосов
/ 22 июля 2011

Почему бы не вернуть DataRow вместо DataTable, если вы знаете, что вернете только 1 строку?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...