首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套循环到IDataReader

嵌套循环到IDataReader
EN

Stack Overflow用户
提问于 2017-03-23 15:11:23
回答 1查看 105关注 0票数 0

我有一个程序可以使用DataTable将一个巨大的SqlBulkCopy (2.000.000到70.000.000行,取决于配置)写入数据库。

我决定将填充此表的循环更改为IDataReader,因为行数通常会导致OutOfMemoryException

表的填充方式如下

代码语言:javascript
复制
// int[] firsts;
// string[] seconds;
// byte[] thirds;
var table = new DataTable();
foreach(var f in firsts)
{
    foreach(var s in seconds)
    {
        foreach(var t in thirds)
        {
            var row = table.NewRow();
            row[0] = f;
            row[1] = s;
            row[2] = t;
            table.Rows.Add(row);
        }
    }
    // here I also bulk load the table and clear it
}

因此,在我的IDataReader类中,我将按索引循环。这是我的尝试。

代码语言:javascript
复制
class TableReader : IDataReader
{
    bool Eof = false;

    int FirstIndex;
    int SecondIndex;
    int ThirdIndex;

    //those are populated via constructor
    int[] firsts;
    string[] seconds;
    byte[] thirds;

    // this will be retrieved automatically via indexer
    object[] Values;

    public bool Read()
    {
        if(ThirdIndex != thirds.Length
            && SecondIndex < seconds.Length
            && FirstIndex < firsts.Length)
        {
            Values[0] = firsts[FirstIndex];
            Values[1] = seconds[SecondIndex];
            Values[2] = thirds[ThirdIndex++];
        }
        else if(SecondIndex != seconds.Length)
        {
            ThirdIndex  = 0;
            SecondIndex++;
        }
        else if(FirstIndex != firsts.Length)
        {
            SecondIndex = 0;
            FirstIndex++;
        }
        else
        {
            Eof = true;
        }
        return !Eof;
    }
}

我使用带中断的while(true)循环而不是Eof创建了这段代码,但我似乎想不出如何做到这一点。

有人能帮忙吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-02 01:33:50

实际上,如果您实现了IDataReader并使用“产生返回”关键字来提供行,这实际上是可能的。IDataReader的实现有点麻烦,但它一点也不复杂。下面的代码可以调整为将一兆字节的数据加载到数据库中,并且不会耗尽内存。

  • 我用一个对象数组替换了DataRow对象,该对象数组在整个数据读取过程中被重用。
  • 因为没有DataTable对象来表示列,所以我不得不通过分别存储数据类型和列名来做到这一点。 类TestDataReader : IDataReader { int[]第一={ 1、2、3、4 };string[]秒={ "abc“、"def”、"ghi“};byte[]三分之二={ 0x30、0x31、0x32 };//每列的数据类型。Type[] dataTypes ={ typeof(int)、typeof of (String)、typeof of(字节) };//每个列的名称。string[]名称={“第一”、“秒”、“第三”};//此函数使用协同学将“推送”方法转换为“拉”方法。私有IEnumerable GetRows() { //只是重复使用相同的数组。object[] row =新object3;foreach (第一var f){ foreach (var s以秒计){ foreach (var t in三分之一){ row = f;row1 = s;row2 = t;产量返回行;} //在这里,我还批量加载了他的表,并清除了}} //下面的所有内容。IEnumerator rowProvider;公共TestDataReader() { rowProvider = GetRows().GetEnumerator();}公共对象thisint int i{ get {返回GetValue(i);}}公共对象字符串名{ get {返回GetValue(GetOrdinal(名称));}公共int深度{ get {返回0;}公共int FieldCount { get {返回dataTypes.Length;}公共bool IsClosed {获取{返回假;}公共int RecordsAffected {获取{返回0;} //它们实际上什么也做不了。公共空关闭(){ Type ();} public void (){ rowProvider.Dispose();}公共字符串GetDataTypeName(int i) {返回dataTypesi.Name;}公共类型GetFieldType(int i) {返回dataTypesi;} //这些函数得到基本的数据类型。公共bool GetBoolean(int i) {返回(bool) rowProvider.Currenti;}公共字节GetByte(int i) {返回(字节) rowProvider.Currenti;} public char GetChar(int i) {返回(char) rowProvider.Currenti;} public DateTime GetDateTime(int i) {int (DateTime) rowProvider.Currenti;}公共十进制GetDecimal(int i) {返回(十进制) rowProvider.Currenti;}公共双GetDouble(int i) {返回(双) rowProvider.Currenti;}公共浮点数GetFloat(int i) {返回(浮点数) rowProvider.Currenti;} public Guid GetGuid(int i) { return (Guid) rowProvider.Currenti;} public short GetInt16(int i) { long ( int ) rowProvider.Currenti;} public int GetInt32(int i) { return (Int) rowProvider.Currenti;} public long GetInt64(int i) {long (long) rowProvider.Currenti;} public string GetString(int i) {long (string) rowProvider.Currenti;}公共对象GetValue(int i) {返回(对象) rowProvider.Currenti;}公共字符串GetName(int i) {返回名称;} public bool IsDBNull(int i) { object obj = rowProvider.Currenti;返回obj == null \x\ obj是DBNull;} //查找给定其名称的字段号。公共int GetOrdinal(字符串名){返回Array.FindIndex(名称,x => x.Equals(name,StringComparison.OrdinalIgnoreCase));} //填充给定当前数据行的“值”。公共int GetValues(object[]值){ if (值== null) {== 0;}Math.Min{ int len = Math.Min(values.Length,rowProvider.Current.Length);Array.Copy(rowProvider.Current,值,len);返回len;} //此读取器只支持单个结果集。公共bool NextResult() {返回false;} //移到下一行。public bool (){返回rowProvider.MoveNext();} //不要费心以任何有意义的方式实现这些。公共长GetBytes(int i,long fieldOffset,byte[]缓冲区,int缓冲器偏移量,int长度){抛出新的NotImplementedException();}公共长GetChars(int i,long fieldoffset,char[]缓冲区,int缓冲器偏移量,int长度){抛出新NotImplementedException();} public IDataReader GetData(int i) {抛出新的NotImplementedException();} public DataTable GetSchemaTable() {返回null;}}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42980028

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档