在构造函数中调用 AddSubClassHierarchy() 导致 Query<T> 中没有结果

Calling AddSubClassHierarchy() in constructor causes no results in Query<T>

当我阅读 Maven docs regarding Document Hierarchy 时,我认为在通用参数是基类的情况下调用 AddSubClassHierarchy() 会自动映射所有子类型。文档内容如下:

// Alternatively, you can use the following:
// _.Schema.For<ISmurf>().AddSubClassHierarchy();
// this, however, will use the assembly
// of type ISmurf to get all its' subclasses/implementations. 
// In projects with many types, this approach will be undvisable.

我觉得应该使用反射,所以我不必指定每个子类。我的层次结构是 CoreObject-->Actor-->Customer.

但是当我添加 AddSubClassHierarchy 时,Query<T> 失败并且 returns 什么都没有:

        store = DocumentStore.For(_ =>
        {
            // Marten will create any new objects that are missing,
            // attempt to update tables if it can, but drop and replace
            // tables that it cannot patch. 
            _.Connection("host=localhost;database=marten;password=root;username=postgres");
            _.Schema.For<Customer>().Index(x => x.PopulationRegistryNumber);
            _.Schema.For<CoreObject>().AddSubClassHierarchy(); // CoreObject is base class to Actor, that is base class for Customer
            _.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
        });

然后当我尝试时:

        using (var session = store.OpenSession())
        {
            list = session.Query<Actor>().Where(a => a.Username == "asdasd").ToList();
        }

它失败了,returns 没有项目。所有其他 Query<T> 也都失败了,比如这个:

        using (var session = store.LightweightSession())
        {
            List<Customer> list = session.Query<Customer>().ToList();
            return list;
        }

列表将包含 0 个元素。如果我删除 _.Schema.For<CoreObject>().AddSubClassHierarchy();,我会从 session.Query<Customer>().

得到结果

编辑

我试着按照杰里米说的去做;手动定义层次结构,如下所示:

public MartenDbHandler()
{
    StoreOptions so = new StoreOptions();
    // here it is: CoreObject-->Actor-->Customer
    so.Schema.For<CoreObject>().AddSubClassHierarchy(typeof(Actor), typeof(Customer));
    so.Connection("host=localhost;database=marten;password=root;username=postgres");
    so.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
    SetTableMeta(so);
    store = new DocumentStore(so);
}

起初,没有任何变化。我需要再次清除并插入对象。然后我意识到所有对象最终都在 one table: mt_doc_coreobject

然后当我搜索时,它起作用了:

    List<Actor> list3 = martenDbHandler.Select<Actor>(c => c.Username == "YS3M");
    Console.WriteLine($"SELECT Actor {list3.Count}"); // = 1

但我当然意识到将所有对象放在一个 table 中是一个简单的解决方法,但我认为我阅读了其他一些警告,我不确定我是否解释正确:

There's a couple things to be aware of with type hierarchies:

  • A document type that is either abstract or an interface is automatically ssumed to be a hierarchy
  • If you want to use a concrete type as the base class for a hierarchy, you will need to explicitly configure that by adding the subclasses as shown above
  • At this point, you can only specify "Searchable" fields on the top, base type
  • The subclass document types must be convertable to the top level type. As of right now, Marten does not support "structural typing", but may in the future
  • Internally, the subclass type documents are also stored as the parent type in the Identity Map mechanics.
  • Many, many hours of banging my head on my desk were required to add this feature.

最糟糕的部分似乎是"At this point, you can only specify "顶部的可搜索“字段,基本类型”,但我在用户名上做了一个Query<>,它在基本类型中不存在CoreObject(它存在于Actor)。所以我不确定那是什么意思?

更新

Marten 对 "searchable" 的意思是 "indexable"?因为我不能再在子类中存在的 属性 上创建索引,所以看起来。

所以,我想我有答案了:

添加以下行,将假定所有子类都持久化在顶层 table,因此所有 ActorCustomer 都将持久化在 [=13] =]table,而不是自己特定的tables.

所以,如果你添加下面的行,Marten 会假设是这种情况,但是如果对象已经在他们自己的 tables 中保存(在添加下面的行之前),则不会有结果成立。

因此,这一行:

so.Schema.For<CoreObject>().AddSubClassHierarchy();

然后将要求您重新插入对象,然后它们会出现在 mt_doc_coreobject