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

时间:2015-11-25 19:50:37

标签: c# sql-server performance collections sqldatareader

当我认为很容易实现时,我很难完成任务。

说我有车对象

(WC_CODE, EFF_TO)

在这些行中有一个public class tblCarObj { public String Model; public Int32 Year; } 的实现,它基于对象成员未知的事实(这是唯一的原因吗?)

这对于通用功能很好,但如果需要,我会牺牲性能功能。我想知道为什么两个链接(见下文)都使用这种方法。

我可以简单地使用reflection

而不是

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

其中:

  • 数据库表已准备就绪
  • DataBase Table与DataObject成员匹配
  • 两者在编译时都是已知的。

并直接在List<tblCarObj> 上使用它而不是更复杂的对象,例如SQLBulckCopy

2 个答案:

答案 0 :(得分:0)

您要求运行时和编译器执行一些在不反映类型的情况下无法执行的操作。

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

可以做你想做的事,但你必须手动编码。存在库的原因是因为反射使你可以避免额外的工作。

答案 1 :(得分:0)

需要进一步测试才能尝试

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

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

  • 如果将其设为通用只会稍微影响它T 使用:

    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)
        {
        }
    
    }
    

<强> GenericIdataReader

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

}