Marten:不在创建 DocumentStore 的 constructor/factory 调用中定义模式内容(如索引等)
Marten: Define schema stuff (like indexes etc) not in the constructor/factory call to create the DocumentStore
我刚开始测试 Marten (2.9),到目前为止我很喜欢它。但是,我不确定我是否遵循 DocumentStore.For
方法。例如,在我对 Marten 的 "dbhandler" 中,我可以这样写:
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
东西不存在:
...而且我还没有真正找到以任何其他方式设置架构的方法。
我真正想做的是拥有一个接口,当我启动我的应用程序时动态加载和执行(通过反射),它处理这些事情,就像一个 IMartenMetaData
看起来像:
public interface IMartenMetaData
{
SetMetaData(DocumentStore store);
}
然后在 that/those 类 中实现架构内容,但这不起作用,因为我无法使用 DocumentStore 来设置元数据。
保持简单。文档存储应该在您的应用程序中有一个实例,并且您在构造期间定义架构属性。无需抽象商店。
一种方法是您可以创建自己的 DocumentStore 实现。可以参考源码中的测试文档存储类。
更新:
您可以在此处找到示例 https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/TestingDocumentStore.cs
我设法做了一个很好的方法来让它更动态,而不是全部在 DocumentStore 的构建中。
请看下面的代码。这个想法很简单:
单独创建 StoreOptions
在创建 DocumentStore 之前,运行 方法通过反射找到将添加 table 元数据的特定类型的所有 classes
创建文档存储
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 接口的基础class。在下面的示例中,没有使用 base class,但我通常发现有一个 base class 很好(我对另一个 ORM 使用了类似的方法,我实际上使用了 base class).但是,如果您不需要,当然可以删除基数 class。
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);
}
所以,我现在可以为每个类型创建一个 class 我也想添加元数据,如下所示:
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 处理程序保持干净,并将元数据分成特定的 classes 以提高可读性、清晰度和所有其他内容 =)
我刚开始测试 Marten (2.9),到目前为止我很喜欢它。但是,我不确定我是否遵循 DocumentStore.For
方法。例如,在我对 Marten 的 "dbhandler" 中,我可以这样写:
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
东西不存在:
...而且我还没有真正找到以任何其他方式设置架构的方法。
我真正想做的是拥有一个接口,当我启动我的应用程序时动态加载和执行(通过反射),它处理这些事情,就像一个 IMartenMetaData
看起来像:
public interface IMartenMetaData
{
SetMetaData(DocumentStore store);
}
然后在 that/those 类 中实现架构内容,但这不起作用,因为我无法使用 DocumentStore 来设置元数据。
保持简单。文档存储应该在您的应用程序中有一个实例,并且您在构造期间定义架构属性。无需抽象商店。
一种方法是您可以创建自己的 DocumentStore 实现。可以参考源码中的测试文档存储类。
更新: 您可以在此处找到示例 https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/TestingDocumentStore.cs
我设法做了一个很好的方法来让它更动态,而不是全部在 DocumentStore 的构建中。
请看下面的代码。这个想法很简单:
单独创建 StoreOptions
在创建 DocumentStore 之前,运行 方法通过反射找到将添加 table 元数据的特定类型的所有 classes
创建文档存储
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 接口的基础class。在下面的示例中,没有使用 base class,但我通常发现有一个 base class 很好(我对另一个 ORM 使用了类似的方法,我实际上使用了 base class).但是,如果您不需要,当然可以删除基数 class。
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);
}
所以,我现在可以为每个类型创建一个 class 我也想添加元数据,如下所示:
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 处理程序保持干净,并将元数据分成特定的 classes 以提高可读性、清晰度和所有其他内容 =)