我想通过将行存储在临时数据文件中而不是将行保留在内存中的方式,将DataTable替换为实现DataRowCollection的自定义类。

我知道,与内存中的表相比,这会比较慢,但是我有时需要使用根本无法容纳ram(> 4GB数据)的表。我将丢弃该表并在运行结束时删除该临时文件。

表数据来自数据库查询。我知道我可以更改查询以减小返回的数据集的大小。那不是重点。关键是总是存在一些内存限制,我想选择使用慢速的临时文件,而不仅仅是说“您不能这样做”。

是否有预写的类或方法?好像我在这里重塑车轮...

这是我的骨骼起点:

/// <summary>
/// like DataTable, but storing data in a file instead of memory
/// </summary>
public class FileBackedDataTable : DataTable, IIntegrationTest
{
    new public FileBackedDataRowCollection Rows = null;

    // Summary:
    //     Initializes a new instance of the System.Data.DataTable class with no arguments.
    public FileBackedDataTable()
    {
        Rows = new FileBackedDataRowCollection(this);
    }
}

/// <summary>
/// like a DataRowCollection but data is stored in a file, not in memory
/// </summary>
public class FileBackedDataRowCollection : ICollection, IEnumerable, IDisposable
{
    /// <summary>
    /// internally track each file record
    /// </summary>
    class recordInfo
    {
        public long recordPosition;
        public int recordLength;
        public int recordMaxLength;
        public long hash;
    }

    DataTable table;

    ArrayList rows = new ArrayList();

    public FileBackedDataRowCollection(DataTable table)
    {
        this.table = table;
        openBackingFile(table);
    }

    public int Count
    {
        get { return rows.Count; }
    }

    public void Clear()
    {
        rows.Clear();
        truncateBackingFile();
    }

    public DataRow this[int index]
    {
        get
        {
            recordInfo info = (recordInfo)rows[index];
            return readRow(info);
        }
        set
        {
            writeRow(index, value);
        }
    }

    private void writeRow(int index, DataRow value)
    {
        byte[] bytes = rowToBytes(value);
        recordInfo info = (recordInfo)rows[index];
        if (bytes.Length <= info.recordMaxLength)
        {
            info.recordLength = bytes.Length;
            info.hash = value.GetHashCode();
            writeBytes(info.recordPosition, bytes);
        }
        else
        {
            rows[index] = appendRow(bytes, value.GetHashCode());
        }
    }

    private DataRow readRow(recordInfo recordInfo)
    {
        byte[] bytes = readBytes(recordInfo.recordPosition, recordInfo.recordLength);
        DataRow row = bytesToRow(bytes);
        return row;
    }

    public void Add(DataRow r)
    {
        byte[] bytes = rowToBytes(r);
        recordInfo info = appendRow(bytes, r.GetHashCode());
        rows.Add(info);
    }

    private recordInfo appendRow(byte[] bytes, long hash)
    {
        recordInfo info = new recordInfo();
        info.recordLength = bytes.Length;
        info.recordMaxLength = info.recordLength;
        info.recordPosition = appendBytes(bytes);
        info.hash = hash;
        return info;
    }

最佳答案

几乎100%的计划是错误的设计。花一些时间进行重新设计,使用您的同伴数据库而不是FILE,它们是为了处理大数据而创建的。如果需要,您可以使用C#或其他语言(如果数据库允许)编写存储过程。

描述您想要处理数据的方式,您将获得真正问题的真实答案。它要么需要SQL查询,要么如果不能在SQL中完成它,则可以肯定地以某种循环使用较小的数据大小来完成。

10-07 19:55
查看更多