Question about C # interfaces and possibly generics

We have created an internal tool that generates all access to data, each table has a class representing its data and all common operations. (think of a lightweight Entity structure).

These DataAccess objects always have a constructor that receives the connection string, and a load function that receives the SqlDataReader.

Something like that:

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

I want to write a Data Access static method utility that will allow me to write my SQL and get a list of objects in response, following the example of the previous object:

string SQL = "SELECT * FROM Customers WHERE Name=@Name";
List<Customer> customers = GetList<Customer>(connStr, SQL, new SqlParameters("@Name", "John"));

- , , , , generics - , ( + 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;
        }

Btw, DataAccess, - + javascript, javascript (, , ).

- , " " , , , , : eytan@titkadem.co.il

,

+3
4

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 .. ( , ).

+3

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

, , .

:

while (reader.Read())
{
    T item = Activator.CreateInstance(typeof(T), new object[] { connStr }) as T;
    item.Load(reader);
    list.Add(item);
}

( , , . )

, , 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
+2

This will not work as you wish. SQL classes for .net are not strongly typed. It is impossible to tell from the query as SELECT * FROM Customers...an object of which class should be built. This is possible if all of your objects come from the same class, which declares:

public virtual Entity Load(SqlDataReader reader)

and your general method has a limitation:

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

then you can do:

T entity = new T();
entity.Load(reader);
+1
source

Source: https://habr.com/ru/post/1770508/


All Articles