简体   繁体   中英

Generic function to get data from SqlDataReader

I'm creating a generic application to get all the data from different SQL Server tables.

I have a generic function that convert the SqlDataReader to a list:

public static List<T> MapToList<T>(this SqlDataReader dr) where T : new()
{
        List<T> RetVal = null;
        var Entity = typeof(T);
        var PropDict = new Dictionary<string, PropertyInfo>();

        try
        {
            if (dr != null && dr.HasRows)
            {
                RetVal = new List<T>();
                var Props = Entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                PropDict = Props.ToDictionary(p => p.Name.ToUpper(), p => p);

                while (dr.Read())
                {
                    T newObject = new T();

                    for (int Index = 0; Index < dr.FieldCount; Index++)
                    {
                        if (PropDict.ContainsKey(dr.GetName(Index).ToUpper()))
                        {
                            var Info = PropDict[dr.GetName(Index).ToUpper()];

                            if ((Info != null) && Info.CanWrite)
                            {
                                var Val = dr.GetValue(Index);
                                Info.SetValue(newObject, (Val == DBNull.Value) ? null : Val, null);
                            }
                        }
                    }

                    RetVal.Add(newObject);
                }
            }
        }
        catch (Exception)
        {
            throw;
        }

        return RetVal;
}

Now suppose I have this class for my data:

public partial class User
{
    public int Id { get; set; }
    public string Name { get; set; }
} 

I can fetch my data from the table something like this:

const string GetAreasQuery = "select id, name from dbo.user";
SqlDataReader dr = DoQueryToDB(GetAreasQuery);
List<User> userList = dr.MapToList<User>();

Now, I have n different classes like User ( Classroom and so on) and I don't want to write the code above for each class I have. I would like to create a generic GetData to retrieve those information:

public List<T> GetData<T> (string Query_)
{
    SqlDataReader dr = DataReader(Query_);
    List<T> data = new List<T>();
    data = dr.MapToList<T>();
    return data;
} 

where T can be User , Classroom and so on...

I tried this solution but I always have to specify the type:

public object GetData(string Query_, Type type)
{
        SqlDataReader dr = DataReader(Query_);

        if (type == typeof(User))
        {
            List<User> data = new List<User>();
            data = dr.MapToList<User>();
            return data;
        } 
        else if (..) 
        {}

    return null;
}

I'm trying different possibilities but I always obtain an error in GetData<T> function. More precisely in MapToList<T> like: T should be a non abstract type or public constructor without parameters.

You should add a contraint to the method GetData in order to achieve the same constraint level that is found in MapToList, which requires T to have a empty constructor

public List<T> GetData<T>(string Query_) where T : new()
       {
           SqlDataReader dr = DataReader(Query_);
           return  dr.MapToList<T>();

       }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM