Marten项目中的多租户文档管理详解

Marten项目中的多租户文档管理详解

marten .NET Transactional Document DB and Event Store on PostgreSQL marten 项目地址: https://gitcode.com/gh_mirrors/ma/marten

概述

在现代应用开发中,多租户架构是一种常见的设计模式,它允许单个应用实例为多个租户(客户或组织)提供服务,同时保持数据隔离。Marten作为一个.NET平台的文档数据库和事件存储库,提供了强大的多租户支持功能。

多租户基础概念

Marten支持三种多租户模式,通过TenancyStyle枚举表示:

  1. 单租户模式(Single):默认模式,不启用多租户功能
  2. 联合租户模式(Conjoined):通过租户ID实现多租户
  3. 分离租户模式(Separate):通过独立数据库或模式实现多租户(规划中)

租户会话管理

创建租户会话

Marten通过会话(IQuerySession, IDocumentSession)来管理租户范围。创建特定租户的会话非常简单:

// 为"tenant1"租户创建轻量级会话
using (var session = store.LightweightSession("tenant1"))
{
    // 存储用户文档
    session.Store(new User { UserName = "Bill" });
    session.Store(new User { UserName = "Lindsey" });
    await session.SaveChangesAsync();
}

查询租户数据

查询操作会自动限定在当前会话的租户范围内:

using (var query = store.QuerySession("tenant1"))
{
    var users = query.Query<User>()
        .Select(x => x.UserName)
        .ToList();
    // 只会返回"tenant1"租户下的用户
}

默认租户处理

当启用多租户功能时,Marten会为每个记录关联一个租户标识符。如果没有明确指定租户,Marten会使用默认租户ID(Tenancy.DefaultTenantId),其值为*DEFAULT*

可以通过配置禁用默认租户:

storeOptions.Advanced.DefaultTenantUsageEnabled = false;

禁用后,如果尝试使用默认租户创建会话,Marten会抛出DefaultTenantUsageDisabledException异常。

多租户查询技巧

自动租户过滤

当使用特定租户的会话查询时,Marten会自动为查询添加租户过滤条件(如果文档类型是多租户的)。

跨租户查询

有时需要查询多个租户的数据,Marten提供了两种方式:

  1. TenantIsOneOf:查询指定租户列表的数据
// 查询Green和Red租户的数据
var results = await query.Query<Target>()
    .Where(x => x.TenantIsOneOf("Green", "Red") && x.Flag)
    .OrderBy(x => x.Id)
    .Select(x => x.Id)
    .ToListAsync();
  1. AnyTenant:查询所有租户的数据
// 查询所有租户的数据
var results = query.Query<Target>()
    .Where(x => x.AnyTenant() && x.Flag)
    .OrderBy(x => x.Id)
    .Select(x => x.Id)
    .ToArray();

租户配置策略

全局配置

可以在存储级别配置租户策略,应用于所有文档:

var store = DocumentStore.For(opts =>
{
    opts.Connection("connection_string");
    opts.Policies.AllDocumentsAreMultiTenanted();
});

文档级配置

也可以为特定文档类型配置租户策略:

var store = DocumentStore.For(opts =>
{
    opts.Connection("connection_string");
    opts.Schema.For<User>().MultiTenanted();
    opts.Schema.For<Region>().SingleTenanted();
});

租户分区优化(7.26+)

对于使用联合多租户的应用,可以通过PostgreSQL表分区功能提升性能。Marten支持多种分区策略:

  1. 列表分区(LIST):按租户ID列表分区
storeOptions.Policies.AllDocumentsAreMultiTenantedWithPartitioning(x =>
{
    x.ByList()
        .AddPartition("t1", "T1")
        .AddPartition("t2", "T2");
});
  1. 哈希分区(HASH):按租户ID哈希值分区
x.ByHash("one", "two", "three");
  1. 范围分区(RANGE):按租户ID范围分区
x.ByRange()
    .AddRange("north_america", "na", "nazzzzzzzzzz")
    .AddRange("asia", "a", "azzzzzzzz");

也可以让外部工具管理分区:

x.ByExternallyManagedListPartitions();

单表分区配置

为特定文档类型配置分区:

opts.Schema.For<User>().MultiTenantedWithPartitioning(x =>
{
    x.ByExternallyManagedListPartitions();
});

最佳实践

  1. 明确租户边界:始终确保操作在正确的租户上下文中执行
  2. 谨慎使用跨租户查询:仅在确实需要时使用,避免意外数据泄露
  3. 考虑分区策略:根据租户数量和访问模式选择合适的分区方式
  4. 测试默认租户行为:确保理解并测试默认租户的行为是否符合预期

通过合理利用Marten的多租户功能,可以构建既安全又高效的SaaS应用,确保不同客户数据的严格隔离,同时保持良好的系统性能。

marten .NET Transactional Document DB and Event Store on PostgreSQL marten 项目地址: https://gitcode.com/gh_mirrors/ma/marten

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郁勉能Lois

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值