我正在使用NDatabase进行一些非常简单的对象存储-基本上是建立一个持久的工作队列。计划是创建一组对象,将它们持久保存到磁盘,然后按属性之一的顺序读回它们。我无法使“排序的”部分正常工作-NDatabase引发异常。

这是我要保留的对象的超类型:

public abstract class Instruction: IComparable, IComparable<Instruction>
{
    public virtual DateTime Timestamp
    {
        get;
        set;
    }

    public int CompareTo(Instruction other)
    {
        if (this.Timestamp.Equals(other.Timestamp))
            return 0;

        return (this.Timestamp < other.Timestamp) ? -1 : 1;
    }

    public int CompareTo(object obj)
    {
        var other = obj as Instruction;
        return other == null ? -1 : this.CompareTo(other);
    }
}


这是我创建对象存储的方式:

using (var odb = OdbFactory.Open(storeName))
{
    odb.IndexManagerFor<Instruction>().AddIndexOn("TimestampIndex", "Timestamp");
    foreach (var instruction in instructions)
    {
        odb.Store(instruction);
    }
    odb.IndexManagerFor<Instruction>().RebuildIndex("TimestampIndex");
}


这是稍后如何检索商店的方法:

lock (this.odb)
{
    var q = odb.Query<T>();
    q.Descend("Timestamp").OrderAscending();
    var objectSet = q.Execute<T>(true, 0, maxCount);
    instructions = objectSet.ToList();

    foreach (var instruction in instructions)
    {
        odb.Delete(instruction);
    }

    odb.IndexManagerFor<Instruction>().RebuildIndex("TimestampIndex");

    odb.Commit();
}


这会在NDatabase.Exceptions.OdbRuntimeException调用上引发ToList()。探究异常属性会显示消息


  “ NDatabase抛出异常错误:222:不支持操作:
  复制到”


但是,如果我注释掉q.Descend("Timestamp").OrderAscending();行,则它可以正常工作-尽管显然没有排序。

有人可以帮忙澄清一下吗?

最佳答案

例外是告诉您NDatabase的ICollection<T>AbstractBTreeCollection<T>)基本实现不支持方法CopyTo(),该方法由您正在使用的LINQ扩展方法ToList()调用。

因此,问题就变成了:为什么仅当您使用OrderByAscending进行中介工作时才发生这种情况,而不是直接在Query的结果上发生?

查看NDatabase的源代码,可以看到原因:
http://ndatabase.codeplex.com/SourceControl/latest

if (_inMemory)
{
    if (_query != null && _query.HasOrderBy())
        _result = new InMemoryBTreeCollection<T>(_query.GetOrderByType());
    else
        _result = new SimpleList<T>();
}
else
{
    // result = new InMemoryBTreeCollection((int) nbObjects);
    if (_query != null && _query.HasOrderBy())
        _result = new LazyBTreeCollection<T>(_storageEngine, _returnObjects);
    else
        _result = new LazySimpleListFromOid<T>(_storageEngine, _returnObjects);
}


QueryResultAction<T>.Start()中:


如果您有命令,您将获得实现的实例
AbstractBTreeCollection,不支持CopyTo
如果您没有订购依据,则会获得SimpleListLazySimpleListFromOid的实例,它们确实支持CopyTo


在研究NDatabase的示例时,他们不希望您调用ToList()
https://ndatabase.codeplex.com/wikipage?title=5-minutes-tutorial

这是一个非常痛苦的实现细节。您可能想将其作为与他们的问题提出。

10-07 16:38