通用方法。将 DataReader 的属性分配给通用对象
早上好,我创建了我的第一个通用方法,该方法是从一堆 Google 搜索中拼凑而成的。我希望有人检查一下这个问题,并让我知道我是否违反了任何主要规则,或者是否有方法可以改进此方法。
该方法调用 sql 中的存储过程,然后使用反射根据从 DataReader 架构读取的值分配属性。存储过程经过编码,以便它们返回类所需的确切属性名称。这是代码:
public static List<T> GetList<T>(string SQLServer, string DBName,
string ProcedureName, Dictionary<string, string> Parameters )
where T : new()
{
List<T> list = new List<T>();
//Setup connection to SQL
SqlConnection SqlConn = new SqlConnection(ConnectionString(SQLServer, DBName));
SqlCommand SqlCmd = new SqlCommand(ProcedureName, SqlConn);
SqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader reader;
//Process Parameters if there are any
foreach (KeyValuePair<string, string> param in Parameters)
{
SqlCmd.Parameters.AddWithValue(param.Key, param.Value);
}
SqlConn.Open();
reader = SqlCmd.ExecuteReader();
//Get The Schema from the Reader
//The stored procedure has code to return
//the exact names expected by the properties of T
DataTable schemaTable = reader.GetSchemaTable();
List<string> fields = new List<string>();
foreach (DataRow r in schemaTable.Rows)
{
fields.Add(r[0].ToString());
}
while (reader.Read())
{
T record = new T();
foreach (string field in fields)
{
//Assign the properties using reflection
record.GetType().GetProperty(field).SetValue(
record, reader[field],
System.Reflection.BindingFlags.Default,
null,null,null);
}
list.Add(record);
}
return list;
}
Good Morning, I have created my first generic method pieced together from a bunch of Google Searches. I would like for someone to look this over and let me know if I am breaking any major rules or if there are ways to improve this method.
The method calls a stored procedure in sql and then uses reflection to assign the properties based on the values read from the DataReader schema. The stored procedures are coded so that they return the exact property names expected by the classes. Here is the code:
public static List<T> GetList<T>(string SQLServer, string DBName,
string ProcedureName, Dictionary<string, string> Parameters )
where T : new()
{
List<T> list = new List<T>();
//Setup connection to SQL
SqlConnection SqlConn = new SqlConnection(ConnectionString(SQLServer, DBName));
SqlCommand SqlCmd = new SqlCommand(ProcedureName, SqlConn);
SqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader reader;
//Process Parameters if there are any
foreach (KeyValuePair<string, string> param in Parameters)
{
SqlCmd.Parameters.AddWithValue(param.Key, param.Value);
}
SqlConn.Open();
reader = SqlCmd.ExecuteReader();
//Get The Schema from the Reader
//The stored procedure has code to return
//the exact names expected by the properties of T
DataTable schemaTable = reader.GetSchemaTable();
List<string> fields = new List<string>();
foreach (DataRow r in schemaTable.Rows)
{
fields.Add(r[0].ToString());
}
while (reader.Read())
{
T record = new T();
foreach (string field in fields)
{
//Assign the properties using reflection
record.GetType().GetProperty(field).SetValue(
record, reader[field],
System.Reflection.BindingFlags.Default,
null,null,null);
}
list.Add(record);
}
return list;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不知道我是否会这么做。我可能会首先使用 ORM,例如实体框架。不过,我过去也做过类似的事情,但也有一些缺点:
我唯一肯定要做的就是确保使用 try/catch/finally、try/finally,或者将 SqlConnection、SqlCommand 和 SqlDataReader 包装在 using() 中。我只花了2天重构,因为之前的开发人员没有关闭任何连接或datareader,并且连接池被炸毁并拒绝连接。
I don't know if that's something I would ever do or not. I would probably use an ORM first, e.g. Entity Framework. I have done stuff similar to that in the past, though, and there are some draw-backs:
About the only thing I would definitely say to do is to make sure to use try/catch/finally, try/finally, or wrap SqlConnection, SqlCommand, and SqlDataReader within using()s. I just spent 2 days refactoring because previous developers didn't close any connection or datareader, and the connection pool was blowing up and refusing connections.
虽然这种方法确实有效,但您肯定希望添加一些错误处理。
还有一些现有的库可以为您执行此操作,例如 AutoMapper。您还可以研究其他 ORM,如 SubSonic、Linq2SQL、EntityFramework、NHibernate 等...
还要注意,反射非常慢,尤其是像这样一遍又一遍地执行。如果这是在大型企业重负载系统中,那么您最好在第一次遇到映射时生成动态方法和 IT 代码来执行映射,然后一遍又一遍地重新运行相同的动态方法,而不是依赖反射。
While this approach does work, you would definitely want to add some error handling.
There are also existing libraries out there that would do this for you, like AutoMapper. You could also look into other ORMs, like SubSonic, Linq2SQL, EntityFramework, NHibernate, etc...
Also note that reflection is very slow, especially doing it over and over like this. If this were going to be in a large corporate heavy-load system, you would be better off generating ta dynamic method and IT code to do the mapping the first time the mapping is encountered, then re-running the same dynamic method over and over, instead of relying on reflection.