我们已经构建了一个生成整个数据访问的内部工具,每个表都有一个表示它的数据和所有常见操作的类。(想想轻量级实体框架)。
这些DataAccess对象总是有一个接收连接字符串的构造函数,以及一个接收SqlDataReader的Load函数。
这样的事情:
class Customer
{
public string ConnStr;
public int Id;
public string Name;
Public customers(string connStr)
{
ConnStr = connStr;
}
public Customer Load(SqlDataReader)
{
if(reader.Read())
{
Id = reader["Id"].ToString();
Name = reader["Name"].ToString();
}
}
}
我想编写一个实用程序数据访问静态方法,它允许我编写我的SQL并获得一个对象列表作为回报,遵循上一个对象示例:
string SQL = "SELECT * FROM Customers WHERE Name=@Name";
List<Customer> customers = GetList<Customer>(connStr, SQL, new SqlParameters("@Name", "John"));
我不知道如何处理它,我已经尝试过接口但它们不允许构造函数或静态方法,并且使用泛型 - 我无法调用我需要初始化对象的方法(构造函数+ load),这是我的最新尝试,注释掉了不起作用的部分:
public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
{
List<T> list = new List<T>();
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
SqlCommand cmd = new SqlCommand(SQL, conn);
foreach (SqlParameter param in prms)
{
cmd.Parameters.Add(param);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
//T item = new T(connStr);
//item.Load(reader);
//list.Add(item);
}
}
return list;
}
如果有人知道如何“开源”这样的项目或任何想加入该产品开发的公司 - 请随时与我联系:eytan@titkadem.co.il
提前致谢, 伊藤
答案 0 :(得分:3)
Load
很容易 - 您可以:
interface IDataEntity {
void Load(SqlDataReader reader);
}
然后:
public static List<T> GetList<T>(string connStr, string SQL,
params SqlParameter[] prms) where T : IDataEntity, new()
{
....
T item = new T();
item.Load(reader);
list.Add(item);
}
new T(connStr)
比较棘手 - 它真的需要这个值吗?公共财产将更容易:
interface IDataEntity {
void Load(SqlDataReader reader);
string ConnectionString {get;set;}
}
class Customer : IDataEntity
{ ... }
等。参数化通用构造函数没有任何内置(语言)支持。您可以解决它,但在许多情况下Activator.CreateInstance
的参数化形式足够快(与通过网络进行数据访问相比,反射可以忽略不计)。如果你需要参数化版本,可以使用Expression
等完成(如果你想要一个例子,请告诉我。)
答案 1 :(得分:2)
为什么不将constr传递给方法:
T item = new T();
item.SetConn(connStr);
不要忘记:
public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
where T : new
{
答案 2 :(得分:2)
除非你想改变你的类在构造函数方面的工作方式,否则你需要去反思。
你可以这样做:
while (reader.Read())
{
T item = Activator.CreateInstance(typeof(T), new object[] { connStr }) as T;
item.Load(reader);
list.Add(item);
}
(注意这里,我让上面的循环负责在读者上调用.Read)
请注意,除非通过接口公开Load方法,否则还需要通过反射调用它。
我会这样做:
public interface IDataObject
{
void Load(IDataReader reader);
}
然后为您的客户实施此操作:
public class Customer : IDataObject
{
...
然后为GetList方法添加一个约束:
public List<T> GetList<T>(string connStr, string sql, params SqlParameter[] parameters)
where T : IDataObject
答案 3 :(得分:1)
这不会按你的意愿行事。 .net的SQL类不是强类型的。它不可能从像SELECT * FROM Customers...
这样的查询的查询中说出必须构造的类。如果所有实体派生自声明的单个类,则可以这样做:
public virtual Entity Load(SqlDataReader reader)
并且您的通用方法有约束:
public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
where T : Entity, new()
然后你可以这样做:
T entity = new T();
entity.Load(reader);