我有以下场景,我一直用它来从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"]);
}
}
}
是否有更好或更有效的方法(“这”返回单个数据行以从中提取数据)?这种方法当然有效,但是当我总是只需要处理索引0处的行时,必须键入dt.Rows [0] [string]有点麻烦。请记住我喜欢能够将提取的所有数据层内容保存到单个类中。哪(根据我的理解)意味着我不能使用SqlDataReader,因为它必须在完成后关闭,所以我不能从我的数据层类返回它。
答案 0 :(得分:4)
使用您想要的成员定义一个类作为属性。然后填充并返回该对象。你可以使用像“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;
现在:
答案 1 :(得分:0)
如果您知道只返回1行,为什么不返回DataRow而不是DataTable?
答案 2 :(得分:0)
我写了一个代码生成器,它生成我的数据访问代码,每个存储过程一个类。其中一个选项是您可以指定其结果集由单行组成。用法很简单:生成的代码通过包装器方法调用,该方法强制执行使用契约所需的任何约束,因此:
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
}