使用任何(指定的)对象集合而不使用反射来填充IDataReader

3
我正在努力完成一些本应该很容易实现的事情。比如说,我有一个汽车对象。
public class tblCarObj
{
    public String Model;
    public Int32 Year;
}

在这些代码行中,有一种基于对象成员未知的反射实现(这是唯一的原因吗?)。
这对于通用功能很好,但如果需要,我会为性能而放弃功能。我想知道为什么下面两个链接都使用了这种方法。
我是否可以简单地使用 MyCarReader<tblCarObj> 而不是
    //for this instance.        
    private IEnumerator<T> enumerator = null;

    //List of all public fields in <T>
    private List<FieldInfo> fields = new List<FieldInfo>();

    public MyGenericDataReader(IEnumerable<T> enumerator)
    {
        this.enumerator = enumerator.GetEnumerator();            

        //Find the enumerator of all public fields
        foreach (FieldInfo fieldinfo in typeof(T).GetFields(                
            BindingFlags.Instance |
            BindingFlags.Public))
        {
            fields.Add(fieldinfo);
        }
    }  

有没有一种方法可以在不使用反射的情况下实现这种方法?
背景
任务是将一组对象简单地上传到数据库表中,
List<tblCarObj>

其中:

  • 数据库表已准备好
  • 数据库表与DataObject成员相匹配
  • 两者在编译时均已知。

可以直接在SQLBulckCopy上使用它,而不是像DataTable这样更复杂的对象。


我认为它使用了反射,但是Dapper是一个预构建的库,正好可以满足您的需求。它由StackOverflow的开发人员开发,并用作此网站的后端。 - Scott Chamberlain
@ScottChamberlain 这个问题是,如果我只想让它接受一个已初始化对象的列表,为什么你需要 Dapper?为什么要使用反射,我在这里漏掉了什么? - Jbob Johan
我不明白你想说什么,抱歉。 - Scott Chamberlain
@ScottChamberlain 我想填充一个 SqlDataReader,我可以使用 IDataReader 来完成,我们可以在这些示例中看到如何操作,如果您使用 new List<aknownInitializedObject> 来提供数据而不是使用需要使用反射的泛型,那么它应该会更简单,因为我已经提供了成员信息。 - Jbob Johan
@ScottChamberlain,我只想将其更改为使用特定对象并指定成员,而不是使用反射或任何其他getmember,因为我不要求它获取成员,我想要给它,这样我就可以节省开销,只需键入它的字段-objectfields,这里它们就在,只需使用它们。 - Jbob Johan
@ScottChamberlain,请您再次查看我的答案,因为我现在正在澄清它。如果有任何需要更改或确保不会发生重大事故的地方...请务必评论一下。 - Jbob Johan
2个回答

0

你正在要求运行时和编译器执行一些需要反射类型才能完成的操作。

CLR和编译器了解类型上的属性信息是通过类型元数据实现的。反射是一种查询元数据并以有意义的方式提供它的机制,使我们可以使用它来发现类型的形状和内容。没有它,一个类型本质上就是一个命名的黑盒子。

可以手动编写代码来实现你想要的功能,但这需要额外的工作量。存在这些库的原因是因为反射使你可以避免这种额外的工作。


@JbobJohan 是的。我能为您做些什么? - Mike Hofer

0

需要进一步的测试尝试

  • 消除不必要的映射 更新:测试通过

(当MyTestObject的属性/字段与列相同时,可以获得额外的性能)

  • 如果通用性只会稍微影响它,那么请使用 T using:

    public string sqlCon ="data source=(local);Initial Catalog=XXX;Integrated Security=True";
    public SqlCommand Cmd;
    public SqlConnection Conn;
    public SqlDataReader Drdr;
    public Form1()
    {
        InitializeComponent();
        this.Conn = new SqlConnection(this.sqlCon);
        this.Cmd = new SqlCommand("select * from [tblTestBC]", this.Conn);
        useBulkCopy();
    }
    void justread()
    {
        this.Cmd.Connection.Open();
        this.Drdr = this.Cmd.ExecuteReader();
        if (this.Drdr.HasRows)
            while (this.Drdr.Read())
            {
    
            }
        this.Cmd.Connection.Close();
    }
    void useBulkCopy()
    {
        var bulkCopy = new SqlBulkCopy(this.Cmd.Connection);
        bulkCopy.DestinationTableName = "tblTestBC";
        //bulkCopy.ColumnMappings.Add("age", "age");
        //bulkCopy.ColumnMappings.Add("name", "name");
        this.Cmd.Connection.Open();
        try
        {
    
            using (var dataReader = new mySimpleDataReader())
            {
                bulkCopy.WriteToServer(dataReader);
            }
            this.Cmd.Connection.Close();
        }
        catch (Exception e)
        {
        }
    
    }
    

通用IdataReader

namespace GenericIdataReader
{
    public class MyTestObject
    {
        public int age;
        public string name;
    }
    public class mySimpleDataReader : IDataReader
    {
        private IEnumerator<MyTestObject> enumerator = null;
        public List<MyTestObject> prpLst { get; set; }
        List<MyTestObject> lst()
        {
            var rt = new List<MyTestObject>(5);
            for (int i = 0; i < rt.Capacity; i++)
            {
                var tmp = new MyTestObject { age = i, name = "MyTestObject->"+i };
                rt.Add(tmp);
            }
            return rt;
        }
        public mySimpleDataReader()
        {
            this.prpLst = this.lst();
            this.enumerator = this.prpLst.GetEnumerator();            
        }


        public void Close()
        {
            throw new NotImplementedException();
        }

        public int Depth
        {
            get { throw new NotImplementedException(); }
        }

        public DataTable GetSchemaTable()
        {
            throw new NotImplementedException();
        }

        public bool IsClosed
        {
            get { throw new NotImplementedException(); }
        }

        public bool NextResult()
        {
            throw new NotImplementedException();
        }

        public bool Read()
        {
            return enumerator.MoveNext();
        }

        public int RecordsAffected
        {
            get { throw new NotImplementedException(); }
        }

        public void Dispose()
        {
            this.enumerator.Dispose();
        }

        public int FieldCount
        {
            get { return 2; }// must be setted 
        }

        public bool GetBoolean(int i)
        {
            throw new NotImplementedException();
        }

        public byte GetByte(int i)
        {
            throw new NotImplementedException();
        }

        public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
        {
            throw new NotImplementedException();
        }

        public char GetChar(int i)
        {
            throw new NotImplementedException();
        }

        public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
        {
            throw new NotImplementedException();
        }

        public IDataReader GetData(int i)
        {
            throw new NotImplementedException();
        }

        public string GetDataTypeName(int i)
        {
            throw new NotImplementedException();
        }

        public DateTime GetDateTime(int i)
        {
            throw new NotImplementedException();
        }

        public decimal GetDecimal(int i)
        {
            throw new NotImplementedException();
        }

        public double GetDouble(int i)
        {
            throw new NotImplementedException();
        }

        public Type GetFieldType(int i)
        {
             throw new NotImplementedException();
        }

        public float GetFloat(int i)
        {
            throw new NotImplementedException();
        }

        public Guid GetGuid(int i)
        {
            throw new NotImplementedException();
        }

        public short GetInt16(int i)
        {
            throw new NotImplementedException();
        }

        public int GetInt32(int i)
        {
            throw new NotImplementedException();
        }

        public long GetInt64(int i)
        {
            throw new NotImplementedException();
        }

        public string GetName(int i)
        {
           throw new NotImplementedException();
        }

        public int GetOrdinal(string name)
        {
           throw new NotImplementedException();
        }

        public string GetString(int i)
        {
            throw new NotImplementedException();
        }

        public object GetValue(int i) // this is where data is being pooled
        {
            if (i > 0) return enumerator.Current.name;
// so need to create an object that will hold numeric index or simply change
//this to return an indexed object instead of an enumerator according to parmeter i value
            return enumerator.Current.age;
        }

        public int GetValues(object[] values)
        {
            throw new NotImplementedException();
        }

        public bool IsDBNull(int i)
        {
            throw new NotImplementedException();
        }

        public object this[string name]
        {
            get { throw new NotImplementedException(); }
        }

        public object this[int i]
        {
            get { throw new NotImplementedException(); }
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接