代码之家  ›  专栏  ›  技术社区  ›  Ted

Marten:定义不在构造函数/工厂调用中创建DocumentStore的模式(比如索引等)

  •  0
  • Ted  · 技术社区  · 6 年前

    我刚开始测试 Marten (2.9),到目前为止我很喜欢。但是,我不确定我是否遵循了 DocumentStore.For

        public MartenDbHandler()
        {
            store = DocumentStore.For(_ =>
            {
                _.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
                _.Connection("host=localhost;database=marten;password=root;username=postgres");
                _.Schema.For<Customer>().Index(x => x.PopulationRegistryNumber);
            });
        }
    

    但是很自然,当我初始化数据库并提供连接字符串时,我不想拥有所有的模式代码。

    store 变量,并执行相同的操作,但是 For 不存在的东西:

    enter image description here

    我真正想做的是有一个接口,当我启动我的应用程序时,它是动态加载和执行的(通过反射),处理这些事情,比如 IMartenMetaData 看起来像是:

    public interface IMartenMetaData
    {
        SetMetaData(DocumentStore store);
    }
    

    2 回复  |  直到 5 年前
        1
  •  1
  •   Migg    6 年前

    保持简单。文档存储应该在应用程序中有一个实例,并且在构造期间定义架构属性。不需要抽象商店。

    一种方法是可以创建自己的DocumentStore实现。可以在源代码中引用测试文档存储类。

    更新: https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/TestingDocumentStore.cs

        2
  •  0
  •   Ted    6 年前

    我设法做了一个很好的方法来保持它的动态性,而不是在文档库的构建中。

    请参阅下面的代码。这个想法很简单: 1) 单独创建StoreOptions 2) 在创建DocumentStore之前,运行通过反射查找将添加表元数据的特定类型的所有类的方法

    public MartenDbHandler()
    {
        StoreOptions so = new StoreOptions();
        so.Connection("host=localhost;database=marten;password=root;username=postgres");
        so.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
        SetTableMeta(so);
        store = new DocumentStore(so);
    }
    
    private void SetTableMeta(StoreOptions storeOptions)
    {
        // We get the current assembly through the current class
        var currentAssembly = Assembly.GetExecutingAssembly();
        // we filter the defined classes according to the interfaces they implement
        var stuff = currentAssembly.DefinedTypes.Where(type => type.IsSubclassOf(typeof(MartenTableMetaDataBase))).ToList();
    
        foreach (Type type in stuff)
        {
            IMartenTableMetaData temp = (IMartenTableMetaData)Activator.CreateInstance(type);
            temp.SetTableMetaData(storeOptions);
        }
        OnLogEvent?.Invoke(this, $"{stuff.Count} table meta data initialized");
    }
    

    IMartenTableMetaData是IMartenTableMetaData接口的基类。在下面的例子中,没有使用基类,但是我通常发现有一个基类是很好的(我使用了与另一个ORM类似的方法,在另一个ORM中我实际使用了基类)。但是,如果您不使用基类,则可以删除它。

    internal abstract class MartenTableMetaDataBase : IMartenTableMetaData
    {
        public void SetTableMetaData(StoreOptions storeOptions)
        {
            SetSpecificTableMetaData(storeOptions);
        }
    
        protected abstract void SetSpecificTableMetaData(StoreOptions storeOptions);
    }
    

    以及界面:

    public interface IMartenTableMetaData
    {
        void SetTableMetaData(StoreOptions storeOptions);
    }
    

    所以,我现在也可以为每种要添加元数据的类型创建一个类,如下所示:

    internal class MartenTableMetaDataCustomer : MartenTableMetaDataBase
    {
        protected override void SetSpecificTableMetaData(StoreOptions storeOptions)
        {
            storeOptions.Schema.For<Customer>().Index(x => x.Muni);
        }
    }
    

    internal class MartenTableMetaDataDriver : MartenTableMetaDataBase
    {
        protected override void SetSpecificTableMetaData(StoreOptions storeOptions)
        {
            storeOptions.Schema.For<Driver>().Index(x => x.Username);
        }
    }
    

    等。

    这将保持Marten DB处理程序的干净,并将元数据分成特定的类,以提高可读性、清晰性和所有这些内容=)