问题描述
我想尝试不使用sql语句用类似的代码编写所有方法和类,而是遵循DRY原理。现在,我需要访问一个未知类的属性。
public T Get(string pathToClass,string sqlStatement)
{
sqlConnection connection = new sqlConnection();
connection.ConnectionString = connectionString; //connectionString is field of class.
connection.open();
sqlCommand command = new sqlCommand(sqlStatement);
sqlDataReader reader = command.ExecuteReader();
List<Type> types = new Reflect(pathToClass).GetTypes(); //Reflection is my class library
List<string> names = new Reflect(pathToClass).GetNames(); //it only reads the classes and returns properties's names and types.
object entity = new object(); //idk is it right or not,but seems it is.
for(int i = 0; reader.Read(); i++)
{
entity.someProperty = types[i].Parse(reader[names[i]].ToString()); //There is a wrong point,where I'm confused
}
connection.Close();
return (T)entity;
}
解决方法
如果不使用ORM,则通常的方法是使用静态工厂方法返回原始的DataRow
或IDataRecord
对象,这些方法具有每种类型的静态工厂方法,并且知道如何构造实例的实例。输入IDataRecord
或DataRow
输入该类型。
例如:
//Initial class might look like this:
public class Employee
{
public string FirstName {get;set;}
public string LastName {get;set;}
public int ID {get;set;}
public string Email {get;set;}
public static Employee FromDataRow(DataRow row)
{
return new Employee
{
ID = row["ID"],FirstName = row["FirstName"],LastName = row["LastName"],Email = row["Email"]
};
}
}
//Data access might look like this:
public class DB
{
private static string ConnectionString { get;} = "connection string here";
public static IEnumerable<DataRow> FindEmployeeRecords(string LastName)
{
string sql = "SELECT ID,FirstName,LastName,Email FROM Employee WHERE LastName LIKE @LastName + '%'";
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(sql,cn))
using(var da = new SqlDataAdapter(cmd))
{
cmd.Parameters.Add("@LastName",SqlDbType.NVarChar,80).Value = LastName;
var result = new DataSet();
da.Fill(result);
return results.Tables[0].Rows;
}
}
}
// and then you could use it like this:
var employees = DB.FindEmpoyeeRecords("Smith").Select(Employee.FromDataRow);
foreach (var employee in employees)
{
//...
}
// or you could bind employees to a datasource
当然,您可以使用reflection将DataRow字段映射到对象。您甚至可以将其中的一部分抽象为实用程序方法。但是,您仍然需要每种类型的factory方法(仅需少量代码),反射速度 slow (确实很慢),并且您失去了映射方式的灵活性,如果您希望类字段与表列有所不同。
我们也可以reduce boilerplate code in the database layer。但是,这需要对函数式编程有更好的了解。