我正在向使用 n 层架构的旧 asp.net 应用程序添加新功能。一个基本的例子可以给出
目的
public class Test
{
public int ID{get;set;}
public int name{get;set;}
}
数据访问层
public static List<Test> GetTests()
{
List<Test> list = new List<Test>();
try
{
//codes
SqlDataReader dr = com.ExecuteReader();
while(dr.Read())
list.Add(FillTestRecord(dr))
//codes
}
catch{}
return list;
}
private static Test FillTestRecord(IDataRecord dr)
{
Test test = new Test();
try{test.ID = Convert.ToInt32(dr["ID"]);}
catch{}
try{test.Name = Convert.ToInt32(dr["Name"]);}
catch{}
return test;
}
开发需要我向对象类添加新字段,并且为了可重用性,我对每种类型的对象仅使用一个 Fill*Record 方法。此方法可由许多其他 DAL 方法调用,这些方法的 IDataRecord 可能不包含对象的所有列。因此,我分别为每个属性放置了 try-catch 块。这可确保正确解析 IDataRecord 中的所有可用列。
我的问题是有没有更好的方法呢?这种架构的最佳实践是什么?
更新
在阅读了 David L 和 Anup 的评论/答案后,我尝试了另一种使用扩展方法的方法。方法如下
public static bool TryGetOrdinal(this IDataRecord dr, string column, out int ordinal)
{
try
{
ordinal = dr.GetOrdinal(column);
}
catch(Exception ex)
{
ordinal = -1; //Just setting a value that GetOrdinal doesn't return
return false;
}
return true;
}
所以FillTestRecord
方法是
private static Test FillTestRecord(IDataRecord dr)
{
Test test = new Test();
int ordinal = default(int);
if(dr.TryGetOrdinal("ID",out ordinal))
test.ID = Convert.ToInt32(dr.GetValue(ordinal));
if(dr.TryGetOrdinal("Name",out ordinal))
test.Name = Convert.ToString(dr.GetValue(ordinal));
return test;
}
对此的任何建议都将受到高度赞赏。
更新 03-02-2016
在调试过程中,我发现try-catch
如果GetOrdinal
在DataRecord
. 所以我写了一个新方法来获取 中的列名DataReader
并替换GetOrdinal
为Array.IndexOf
.
public static bool TryGetOrdinal(this IDataRecord dr, string[] columnNames, string column, out int ordinal)
{
ordinal = Array.IndexOf(columnNames, column);
return ordinal >= 0;
}
而我的FillTestRecord
变成——
private static Test FillTestRecord(IDataRecord dr, string[] columnNames)
{
Test test = new Test();
int ordinal = default(int);
if(dr.TryGetOrdinal(columnNames, "id",out ordinal))
test.ID = Convert.ToInt32(dr.GetValue(ordinal));
if(dr.TryGetOrdinal(columnNames, "name",out ordinal))
test.Name = Convert.ToString(dr.GetValue(ordinal));
return test;
}
列名像这样传递给 Fill 方法 -
using (var dr = com.ExecuteReader())
{
string[] colNames = dr.GetColumnNames();
while (dr.Read())
list.Add(FillTestRecord(dr, colNames));
}
'GetColumnNames' 是新的扩展方法 -
public static string[] GetColumnNames(this IDataReader dr)
{
string[] columnNames = new string[dr.FieldCount];
for (int i = 0; i < dr.FieldCount; i++)
{
columnNames[i] = dr.GetName(i).ToLower();
}
return columnNames;
}