You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时修改类属性:Petapoco跨PostgreSQL多Schema复用POCO咨询

动态Schema场景下Petapoco的POCO适配方案

首先明确:运行时直接修改[TableName]特性里的Schema部分不可行。因为.NET的特性是编译阶段就写入元数据的,运行时没办法直接修改特性的属性值。

下面给你几个实用的替代方案:

方案1:用自定义表名提供器动态拼接Schema

Petapoco自带了ITableNameProvider接口,能让你在运行时动态生成带Schema的完整表名,步骤如下:

  1. 实现这个接口,根据当前需要的Schema拼接表名:
public class DynamicSchemaTableNameProvider : ITableNameProvider
{
    // 可以通过构造函数或者属性设置当前要用的Schema
    public string CurrentSchema { get; set; } = "public";

    public string GetTableName(Type pocoType)
    {
        // 从POCO类上获取标记的基础表名
        var tableAttr = pocoType.GetCustomAttribute<TableNameAttribute>();
        if (tableAttr == null)
            throw new InvalidOperationException($"POCO类{pocoType.Name}没标记TableName特性");
        
        // 提取纯表名(假设你把POCO的TableName特性只写表名,比如[TableName("table1")])
        var baseTableName = tableAttr.Value.Split('.').Last();
        // 拼接Schema和表名
        return $"{CurrentSchema}.{baseTableName}";
    }
}
  1. 初始化Petapoco的Database实例时,把这个自定义提供器传进去:
// 假设db是你的Database实例
db.TableNameProvider = new DynamicSchemaTableNameProvider { CurrentSchema = "schema1" };

// 之后用强类型查询时,会自动用schema1.table1
var dataList = db.Fetch<SomePoco>();
// 手动写SQL的话也可以直接调用获取表名的方法
var singleItem = db.Single<SomePoco>($"SELECT * FROM @0 WHERE id = @1", 
    db.TableNameProvider.GetTableName(typeof(SomePoco)), 1);

方案2:手动指定带Schema的表名执行CRUD

如果场景简单,直接在每次操作时手动传入完整表名就行,不用依赖特性:

  • 查询示例:
string targetSchema = "schema1";
var items = db.Fetch<SomePoco>($"SELECT * FROM {targetSchema}.table1");
  • 插入示例:
var newItem = new SomePoco { Id = 2 };
db.Insert($"{targetSchema}.table1", "id", newItem);

这种方式直接,但如果操作多的话代码会有点重复,适合Schema切换不频繁的场景。

方案3:封装扩展方法简化操作

可以给Petapoco的Database类写扩展方法,把Schema切换的逻辑封装起来,减少重复代码:

  1. 先给POCO统一加个基类(可选,主要是约束类型):
public class BasePoco { }

// POCO类只标记基础表名
[TableName("table1")]
[PrimaryKey("id")]
class SomePoco : BasePoco 
{
    [Column("id")]public int Id { get; set; }
    // 其他属性
}
  1. 写扩展方法:
public static class DatabaseExtensions
{
    public static List<T> FetchWithSchema<T>(this Database db, string schemaName) where T : BasePoco
    {
        var tableAttr = typeof(T).GetCustomAttribute<TableNameAttribute>();
        var fullTableName = $"{schemaName}.{tableAttr.Value}";
        return db.Fetch<T>($"SELECT * FROM {fullTableName}");
    }

    // 同理封装Insert、Update等方法
    public static void InsertWithSchema<T>(this Database db, string schemaName, T poco) where T : BasePoco
    {
        var tableAttr = typeof(T).GetCustomAttribute<TableNameAttribute>();
        var primaryKeyAttr = typeof(T).GetCustomAttribute<PrimaryKeyAttribute>();
        db.Insert($"{schemaName}.{tableAttr.Value}", primaryKeyAttr.Value, poco);
    }
}

使用的时候就很简洁:

var targetSchema = "schema1";
var items = db.FetchWithSchema<SomePoco>(targetSchema);

内容的提问来源于stack exchange,提问作者Anchovy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 13:25:18