IDataReader 为输入列表中的每个对象返回多个 IDataRecords

如何解决IDataReader 为输入列表中的每个对象返回多个 IDataRecords

我正在尝试通过使用 sqlBulkcopy 函数并为其提供自定义 IDataReader 来实现将数百万行导入 sql 表的最快方法(我被告知这比尝试创建 DataTable 更快)>

我目前有一个对象列表,这些对象代表我们文档管理系统中的文档。每个文档都有许多属性。这里我们假设它有 4 个属性,分别是它的 GUID、名称、创建日期和文件大小

我将其放入的 sql 表(为了这个问题而简化)有 3 列,它们是文档 GUID、属性名称属性值。

对于输入列表中的第一个文档对象,我需要 IDataReader 为该文档返回 3 个数据记录。它只有 3,因为文档 GUID 是在 3 条记录中的每条记录上返回的值

例如,如果我有以下文档对象

doc.Guid = 7418db3a-6de6-4657-ac0a-c12585c7c3f2 
doc.Name = "Test Document" 
doc.DateCreated = 28/04/2021 
doc.Filesize = 3345

然后 IDataReader 将输出 3 行,如下所示:

DocumentGUID 属性名称 AttributeValue
7418db3a-6de6-4657-ac0a-c12585c7c3f2 名称 测试文档
7418db3a-6de6-4657-ac0a-c12585c7c3f2 DateCreated 28/04/2021
7418db3a-6de6-4657-ac0a-c12585c7c3f2 文件大小 3345

我使用以下网站中的代码作为起点: http://andreyzavadskiy.com/2017/07/03/converting-list-to-idatareader/

为了方便,我复制了下面的代码

public class ListDataReader<T> : IDataReader
        where T : class
{
    #region Private fields
    private IEnumerator<T> _iterator;
    private List<PropertyInfo> _properties = new List<PropertyInfo>();
    #endregion

    #region Public properties
    #endregion

    #region Constructors
    public ListDataReader(IEnumerable<T> list)
    {
        this._iterator = list.GetEnumerator();

        _properties.AddRange(
            typeof(T).GetProperties(
                BindingFlags.GetProperty |
                BindingFlags.Instance |
                BindingFlags.Public |
                BindingFlags.DeclaredOnly
                )
            );
    }
    #endregion

    #region IDataReader implementation
    public int Depth { get; }
    public bool IsClosed { get; }
    public int RecordsAffected { get; }

    public void Close()
    {
        _iterator.dispose();
    }

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

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

    public bool Read()
    {
        return _iterator.MoveNext();
    }
    #endregion

    #region Idisposable implementation
    public void dispose()
    {
        Close();
    }
    #endregion

    #region IDataRecord
    public string GetName(int i)
    {
        return _properties[i].Name;
    }

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

    public Type GetFieldType(int i)
    {
        return _properties[i].PropertyType;
    }

    public object GetValue(int i)
    {
        return _properties[i].GetValue(_iterator.Current,null);
    }

    public int GetValues(object[] values)
    {
        int numberOfcopiedValues = Math.Max(_properties.Count,values.Length);

        for (int i = 0; i < numberOfcopiedValues; i++)
        {
            values[i] = GetValue(i);
        }

        return numberOfcopiedValues;
    }

    public int Getordinal(string name)
    {
        var index = _properties.Findindex(p => p.Name == name);

        return index;
    }

    public bool GetBoolean(int i)
    {
        return (bool) GetValue(i);
    }

    public byte GetByte(int i)
    {
        return (byte) GetValue(i);
    }

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

    public char GetChar(int i)
    {
        return (char) GetValue(i);
    }

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

    public Guid GetGuid(int i)
    {
        return (Guid) GetValue(i);
    }

    public short GetInt16(int i)
    {
        return (short) GetValue(i);
    }

    public int GetInt32(int i)
    {
        return (int) GetValue(i);
    }

    public long GetInt64(int i)
    {
        return (long) GetValue(i);
    }

    public float GetFloat(int i)
    {
        return (float) GetValue(i);
    }

    public double GetDouble(int i)
    {
        return (double) GetValue(i);
    }

    public string GetString(int i)
    {
        return (string) GetValue(i);
    }

    public decimal GetDecimal(int i)
    {
        return (decimal) GetValue(i);
    }

    public DateTime GetDateTime(int i)
    {
        return (DateTime) GetValue(i);
    }

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

    public bool Isdbnull(int i)
    {
        return GetValue(i) == null;
    }

    public int FieldCount
    {
        get { return _properties.Count; } 
    }

    object IDataRecord.this[int i]
    {
        get { return GetValue(i); }
    }

    object IDataRecord.this[string name]
    {
        get { return GetValue(Getordinal(name)); }
    }
    #endregion
}

任何人都可以就如何修改它以产生我想要的输出提供任何指导吗?

解决方法

您可以使用 LINQ 的 dev-master-01 NetworkUnavailable: False MemoryPressure: False DiskPressure: False PIDPressure: False Ready: True dev-master-02 NetworkUnavailable: False MemoryPressure: False DiskPressure: False PIDPressure: False Ready: True dev-master-03 NetworkUnavailable: False MemoryPressure: False DiskPressure: False PIDPressure: False Ready: True SelectMany 将多条记录传递给 yield return 的构造函数,因为它会接受任何 ListDataReader

IEnumerable<T>

对于匿名类型,您还需要这个小辅助函数:

var list = new List<Document> {
    new Document {
        Guid = 7418db3a-6de6-4657-ac0a-c12585c7c3f2,Name = "Test Document",DateCreated = 28/04/2021,Filesize = 3345,}
};

var reader = NewListDataReader(list.SelectMany(doc =>
    new []
    {
        new {
            DocumentGUID = doc.Guid,AttributeName = "Name",AttributeValue = doc.Name,},new {
            DocumentGUID = doc.Guid,AttributeName = "DateCreated",AttributeValue = doc.DateCreated.ToString(),AttributeName = "Filesize",AttributeValue = doc.Filesize.ToString(),}));

或者你甚至可以创建一个单独的结构而不是匿名对象:

ListDataReader NewListDataReader<T>(IEumerable<T> source)
{
    return new ListDataReader(source);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?