Marten:在构造函数中调用AddSubClassHierarchy()在Query <t>

时间:2018-08-16 00:38:58

标签: c# marten

当我阅读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.

在我看来,将使用Reflection,因此不必指定每个子类。我的等级为CoreObject-->Actor-->Customer

但是当我添加AddSubClassHierarchy时,Query<T>失败并且什么也不返回:

        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();
        }

失败,不返回任何项目。其他所有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);
}

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

当我搜索时,它会起作用:

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

但是我当然知道将所有对象放在一个表中是一个简单的解决方法,但是我想我也阅读了其他一些警告,但我不确定我是否正确解释了

  

类型层次结构需要注意几件事:

     
      
  • 自动将抽象类型或接口的文档类型定为层次结构
  •   
  • 如果要将具体类型用作层次结构的基类,则需要通过添加子类来显式配置该类,如上所示
  •   
  • 目前,您只能在顶部基本类型中指定“可搜索”字段
  •   
  • 子类文档类型必须可以转换为顶级类型。如   目前,Marten不支持“结构化类型”,但可能   未来
  •   
  • 在内部,子类类型文档也作为父类型存储在Identity Map机制中。
  •   
  • 要添加此功能,需要很多时间在桌子上敲打我的头。
  •   

最糟糕的部分似乎是“这时,您只能在顶部,基本类型指定“ Searchable”字段”,但是我在用户名上做了一个Query<>,但该用户名在基础中不存在类型CoreObject(存在于Actor中)。所以我不确定这意味着什么?

更新

Marten所说的“可搜索的”必须是“可索引的”?因为我无法再在子类中存在的属性上创建索引,所以。

1 个答案:

答案 0 :(得分:0)

所以,我想我有答案:

添加以下行,将假定所有子类都保留在顶级表中,因此所有ActorCustomer都将保留在mt_doc_coreobject表中,而不是他们自己的特定表格。

因此,如果添加下面的行,Marten会是这种情况,但是如果对象已经保留在自己的表中(添加下面的行之前),则不会找到结果。

因此,这一行:

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

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