【问题标题】:A question regarding c# interfaces and maybe generics关于 c# 接口和泛型的问题
【发布时间】:2011-04-28 00:01:58
【问题描述】:

我们已经构建了一个内部工具来生成整个数据访问,每个表都有一个代表它的数据和所有常见操作的类。(想想轻量级实体框架)。

这些 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"));

我不知道如何处理它,我尝试过接口,但它们不允许构造函数或静态方法,并且使用泛型 - 我无法调用初始化对象所需的方法(构造函数 +加载),这是我最近的尝试,注释掉了不起作用的部分:


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;
        }

顺便说一句,我们有兴趣开源我们的 DataAccess 生成器,这太棒了 - 它允许非常有效地访问数据库对象 + 创建一个 javascript 数据访问层,让您可以从 javascript 完全控制您的数据库(当然这有安全隐患可以管理)。

如果这里有人知道如何“开源”这样的项目或任何想加入该产品开发的公司 - 请随时与我联系:eytan@titkadem.co.il

提前致谢, 伊坦

【问题讨论】:

  • OT,但从纯粹主义者的角度来看,那些域对象对持久性了解很多,这不一定是他们的责任。我还认为 DataContext 可以为您完成大部分绑定,而无需实体中的任何数据访问代码,免费 ExecuteQuery&lt;T&gt;
  • Lasse 提出了一个有趣的观点,即谁调用了 Read;在许多方面,最好接受IDataRecord 而不是IDataReader/SqlDataReader - 假设它们只需要一行。

标签: c# asp.net generics data-access-layer


【解决方案1】:

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 等来完成(如果您需要示例,请告诉我)。

【讨论】:

  • 嗨 Marc,非常感谢,唯一的更正是 new() 约束应该出现在 IDataEntity 之后。
【解决方案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

【讨论】:

  • Read 的好地方;实际上,我想知道IDataRecord 会不会更好。
  • 使用 IDataRecord 可能会更好,同意。
【解决方案3】:

这不会如您所愿。 .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);

【讨论】:

    【解决方案4】:

    为什么不将 const 传递给方法:

    T item = new T();
    item.SetConn(connStr);
    

    别忘了:

    public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
      where T : new
    {
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 2012-01-27
      相关资源
      最近更新 更多