C#DataTable(DataRowCollection)存储在一个临时文件中,而不是内存?

时间:2011-05-19 21:01:27

标签: c# memory datatable temporary-files

我想通过将行存储在临时数据文件中而不是将它们保存在内存中来将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;
    }

3 个答案:

答案 0 :(得分:2)

最近,我一直在寻找System.Data.SQLite来保存一些应用程序数据,而不是自己编写一个。

如何使用SQLite创建临时文件并在那里加载旧数据?然后你可以像使用本地文件一样使用它,并在咀嚼后删除。

答案 1 :(得分:1)

差不多100%你的计划是糟糕的设计。花一些时间重新设计,使用你的同伴数据库而不是文件,他们有点创建来操纵大块数据。如果你需要,你可以用C#或其他语言编写存储过程。

描述您想要操纵数据的方式,您将获得真实问题的真实答案。它要么需要SQL查询,要么不能在SQL中完成,它可以在某种类型的循环中完成,几乎可以肯定地使用较小的数据大小。

答案 2 :(得分:0)

您可以使用DataTable.WriteXml。但我会支持其他人,最好限制你从数据库中获得的记录。