如何将数据读取器数据分配到(T)的通用列表中 [英] How to assign datareader data into generic List ( of T )

查看:104
本文介绍了如何将数据读取器数据分配到(T)的通用列表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将datareader数据分配到通用List(of T)中。



我不想读取特定的列项名称。

示例代码:

 共享函数FormatUserList(作为OracleDataReader的ByVal PoReader)作为List(用户)
Dim oUserList作为新列表(用户)()
Dim oUser作为用户
Dim dt作为新的DataTable
dt = PoReader.GetSchemaTable()

当PoReader.Read()
Dim index As Integer = 0
oUser =新用户()

oUser.LoginId = Convert.ToString(PoReader(LoginId))
oUser.Password = Convert.ToString(PoReader(Password))
oUser.FirstName = Convert.ToString(PoReader(FirstName ))
oUser.LastName = Convert.ToString(PoReader(LastName))
oUser.NRIC = Convert.ToString(PoReader(NRIC))
oUser.MobileNo = Convert .ToInt64(PoReader(MobileNo))
oUser.Address = Convert.ToString(PoReader(Address))
oUser.Zip = Convert.ToInt64(PoReader(Zip))
oUser.State =转换.ToInt64(PoReader(state))
oUser.UserGroupId = Convert.ToInt64(PoReader(UserGroupId))
oUser.CompanyId = Convert.ToInt64(PoReader(CompanyId))
oUser.Active = Convert.ToInt64(PoReader(Active))
oUserList.Add(oUser)
Loop

返回oUserList
End Function

我需要类似下面的内容,但在将第二行数据循环到 SetValue 。



对象引用未设置为对象的实例。

  Do虽然PoReader.Read()

oUserGroup =新的UserGroups()

Dim type As Type = GetType(UserGroups)
Dim obj As Object = Activator.CreateInstance(type)

对于每一行DataRow在dt.Rows
sColName = row.Field(Of String)(ColumnName)
type.GetProperty(sColName).SetValue(obj,PoReader(row.Field(Of String)(ColumnName)),Nothing)
oUserGroupLis t.Add(obj)
下一行
Loop


解决方案

目前还不清楚 dt 在这里的作用;然而,下面的第二个例子显示了一个基本的基于反射的循环(使用C# - 你必须翻译)。

然而,

然而, ,在这之前,我真的认为你应该看看dapper / a>,它使得数据访问(包括参数化)如下简单:

  string region =North; 
var people = conn.Query< Person>(select * from People where Region = @ region,
new {region})。ToList();

(支持您想要的大多数常见数据场景,包括类型转换)以及比你可以动摇一个基于IL的棒子)



用反射的方式来做这件事很慢,例如:

  static List< T>阅读< T>(IDataReader reader)
其中T:class,new()
{
List< T> results = new List< T>();
Type type = typeof(T);

if(reader.Read())
{
//至少一行:解析属性
PropertyInfo [] props = new PropertyInfo [reader.FieldCount ]。
for(int i = 0; i< props.Length; i ++)
{
var prop = type.GetProperty(reader.GetName(i),
BindingFlags.Instance | BindingFlags.Public);
if(prop!= null&& prop.CanWrite)props [i] = prop;
}

do
{
var obj = new T();
for(int i = 0; i< props.Length; i ++)
{
var prop = props [i];
if(prop == null)continue; //未映射

object val = reader.IsDBNull(i)? null:reader [i];
prop.SetValue(obj,val);
}
results.Add(obj);
} while(reader.Read());
}
返回结果;
}


I would like assign datareader data into generic List ( of T ).

I do not want to read the specific column item name. I want to make it dynamic.

Example code:

Shared Function FormatUserList(ByVal PoReader As OracleDataReader) As List(Of Users)
    Dim oUserList As New List(Of Users)()
    Dim oUser As Users
    Dim dt As New DataTable
    dt = PoReader.GetSchemaTable()

    Do While PoReader.Read()
        Dim index As Integer = 0
        oUser = New Users()

        oUser.LoginId = Convert.ToString(PoReader("LoginId"))
        oUser.Password = Convert.ToString(PoReader("Password"))
        oUser.FirstName = Convert.ToString(PoReader("FirstName"))
        oUser.LastName = Convert.ToString(PoReader("LastName"))
        oUser.NRIC = Convert.ToString(PoReader("NRIC"))
        oUser.MobileNo = Convert.ToInt64(PoReader("MobileNo"))
        oUser.Address = Convert.ToString(PoReader("Address"))
        oUser.Zip = Convert.ToInt64(PoReader("Zip"))
        oUser.State = Convert.ToInt64(PoReader("state"))
        oUser.UserGroupId = Convert.ToInt64(PoReader("UserGroupId"))
        oUser.CompanyId = Convert.ToInt64(PoReader("CompanyId"))
        oUser.Active = Convert.ToInt64(PoReader("Active"))
        oUserList.Add(oUser)
    Loop

    Return oUserList
End Function

I need something like below, but I receive an error when looping the 2nd row data to SetValue.

"Object reference not set to an instance of an object."

Do While PoReader.Read()

  oUserGroup = New UserGroups()

  Dim type As Type = GetType(UserGroups) 
  Dim obj As Object = Activator.CreateInstance(type)

    For Each row As DataRow In dt.Rows
        sColName = row.Field(Of String)("ColumnName")
        type.GetProperty(sColName).SetValue(obj, PoReader(row.Field(Of String)("ColumnName")), Nothing)
        oUserGroupList.Add(obj)
    Next row
Loop

解决方案

It is unclear what the role of dt is here; however, a very basic reflection-based loop (using C# - you would have to translate) is shown in the second example below.

However, before doing that, I really think you should take a look at "dapper", which makes data access (including parameterization) as simple as:

string region = "North";
var people = conn.Query<Person>("select * from People where Region=@region",
           new { region }).ToList();

(with support for most common data scenarios you would want, including type translation - and more insane optimization than you can shake an IL-based stick at)

And to do it the slow way with reflection, something like:

static List<T> Read<T>(IDataReader reader)
    where T : class, new()
{
    List<T> results = new List<T>();
    Type type = typeof(T);

    if (reader.Read())
    {
        // at least one row: resolve the properties
        PropertyInfo[] props = new PropertyInfo[reader.FieldCount];
        for (int i = 0; i < props.Length; i++)
        {
            var prop = type.GetProperty(reader.GetName(i),
                BindingFlags.Instance | BindingFlags.Public);
            if(prop != null && prop.CanWrite) props[i] = prop;
        }

        do
        {
            var obj = new T();
            for (int i = 0; i < props.Length; i++)
            {
                var prop = props[i];
                if (prop == null) continue; // not mapped

                object val = reader.IsDBNull(i) ? null : reader[i];
                prop.SetValue(obj, val);
            }
            results.Add(obj);
        } while (reader.Read());
    }
    return results;
}

这篇关于如何将数据读取器数据分配到(T)的通用列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆