Marten文档存储中的元数据跟踪机制详解
概述
Marten作为一个强大的.NET文档数据库库,提供了完善的元数据跟踪功能。这些功能可以帮助开发者更好地管理和理解文档数据的变化历史、来源以及状态信息。本文将详细介绍Marten中的元数据跟踪机制,包括默认启用的元数据字段、可选字段以及如何自定义元数据映射。
元数据类型与默认设置
Marten支持多种元数据字段,部分字段默认启用,部分则需要显式配置:
默认启用的元数据字段
- 最后修改时间(mt_last_modified):记录文档最后一次被修改的时间戳
- 版本号(mt_version):Guid类型的乐观并发控制标识
- .NET类型信息(mt_dotnet_type):存储文档对应的.NET类型全名
可选配置的元数据字段
- 关联ID(correlation_id):用于追踪业务流程的字符串标识符
- 原因ID(causation_id):表示操作原因的字符串标识符
- 自定义头信息(headers):键值对形式的扩展元数据
- 创建时间(mt_created_at):文档首次创建的时间戳
- 软删除标记(mt_deleted):标记文档是否被软删除
- 软删除时间(mt_deleted_at):记录文档被软删除的时间
元数据配置方式
全局配置
可以通过Policies.ForAllDocuments
方法为所有文档类型统一启用元数据字段:
var store = DocumentStore.For(opts =>
{
opts.Connection("连接字符串");
opts.Policies.ForAllDocuments(x =>
{
x.Metadata.CausationId.Enabled = true;
x.Metadata.CorrelationId.Enabled = true;
x.Metadata.Headers.Enabled = true;
x.Metadata.CreatedAt.Enabled = true;
});
});
按文档类型配置
也可以为特定文档类型单独配置元数据:
opts.Schema.For<User>().Metadata(x =>
{
x.CorrelationId.Enabled = true;
x.CausationId.Enabled = true;
x.Headers.Enabled = true;
});
元数据值设置
会话级别设置
可以在文档会话级别设置关联ID和原因ID:
public void SettingMetadata(IDocumentSession session, string correlationId, string causationId)
{
session.CorrelationId = correlationId;
session.CausationId = causationId;
}
头信息设置
头信息可以设置键值对:
public void SetHeader(IDocumentSession session, string sagaId)
{
session.SetHeader("saga-id", sagaId);
}
文档属性映射
Marten支持将元数据映射到文档类的属性上:
public class DocWithMetadata
{
public Guid Id { get; set; }
public Guid Version { get; set; }
public string Causation { get; set; }
public bool IsDeleted { get; set; }
}
opts.Schema.For<DocWithMetadata>().Metadata(m =>
{
m.Version.MapTo(x => x.Version);
m.CausationId.MapTo(x => x.Causation);
m.IsSoftDeleted.MapTo(x => x.IsDeleted);
});
标记接口简化配置
Marten提供了几个标记接口来简化常见元数据的映射:
- ITracked接口:自动映射关联ID、原因ID和最后修改者
public class MyTrackedDoc: ITracked
{
public Guid Id { get; set; }
public string CorrelationId { get; set; }
public string CausationId { get; set; }
public string LastModifiedBy { get; set; }
}
- IVersioned接口:自动映射版本号并启用乐观并发控制
public class MyVersionedDoc: IVersioned
{
public Guid Id { get; set; }
public Guid Version { get; set; }
}
禁用元数据
如果需要最小化存储开销,可以禁用所有元数据字段:
var store = DocumentStore.For(opts =>
{
opts.Connection("连接字符串");
opts.Policies.DisableInformationalFields();
});
基于修改时间的查询
Marten提供了便捷的扩展方法来查询特定时间段内修改的文档:
public async Task QueryByModificationTime(IQuerySession session)
{
var fiveMinutesAgo = DateTime.UtcNow.AddMinutes(-5);
var tenMinutesAgo = DateTime.UtcNow.AddMinutes(-10);
var recents = await session.Query<Target>()
.Where(x => x.ModifiedSince(tenMinutesAgo))
.Where(x => x.ModifiedBefore(fiveMinutesAgo))
.ToListAsync();
}
最佳实践
- 在分布式系统中,推荐启用correlation_id和causation_id以便追踪请求链路
- 对于需要审计的场景,建议保留所有元数据字段
- 性能敏感场景可以考虑禁用不必要的元数据字段
- 使用标记接口可以简化常见元数据映射的配置
通过合理利用Marten的元数据跟踪功能,开发者可以构建更加健壮、可维护的应用程序,同时获得更好的数据可观测性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考