【问题标题】:ServiceStack.Ormlite single poco map to many tablesServiceStack.Ormlite 单个 poco 映射到多个表
【发布时间】:2014-01-23 02:04:28
【问题描述】:

我知道 Servicestack.Ormlite 设置为 poco 和数据库表之间的 1:1 映射。我有一种情况,我将拥有一组具有相同结构的表,并且它们是根据需要创建的。我正在尝试找到一种方法来做一些事情,我可以继续使用IDbConnection 并在 CRUD 操作中指定表名。

类似

using(var db = _conn.OpenDbConnection()){
    db.SaveAll(objList, "DIFFERENT_TABLE");
}

我可以轻松地创建和删除表。我希望我可以使用ExpressionVisitor 或其他东西来帮助在执行之前更改表名。该项目的要求之一是它与数据库无关,这就是我试图不手动写出 SQL 的原因。

解决方案 如果有人想要更多示例,我最终会创建以下几个函数。

public static List<T> SelectTable<T>(this IDbConnection conn, string tableName) {
        var stmt = ModelDefinition<T>.Definition.SqlSelectAllFromTable;
        stmt = stmt.Replace(ModelDefinition<T>.Definition.Name, tableName.FmtTable());
        return conn.Select<T>(stmt);
}

public static List<T> SelectTableFmt<T>(this IDbConnection conn, string tableName, string sqlFilter,
        params object[] filterParams) {
        var stmt = conn.GetDialectProvider().ToSelectStatement(typeof (T), sqlFilter, filterParams);
        stmt = stmt.Replace(ModelDefinition<T>.Definition.Name, tableName.FmtTable());
        return conn.Select<T>(stmt);
}

public static void InsertTable<T>(this IDbConnection conn, T obj, string tablename) {
        var stmt = conn.GetDialectProvider().ToInsertRowStatement(null, obj);
        stmt = stmt.Replace(obj.GetType().Name, tablename.FmtTable());
        conn.ExecuteSql(stmt);
}

public static int SaveAll<T>(this IDbConnection conn, string tablename, IEnumerable<T> objs) {
        var saveRows = objs.ToList();
        var firstRow = saveRows.FirstOrDefault();
        if (Equals(firstRow, default(T))) return 0;

        var defaultIdValue = firstRow.GetId().GetType().GetDefaultValue();

        var idMap = defaultIdValue != null
            ? saveRows.Where(x => !defaultIdValue.Equals(x.GetId())).ToSafeDictionary(x => x.GetId())
            : saveRows.Where(x => x.GetId() != null).ToSafeDictionary(x => x.GetId());

        var existingRowsMap = conn.SelectByIds<T>(tablename, idMap.Keys).ToDictionary(x => x.GetId());
        var modelDef = ModelDefinition<T>.Definition;
        var dialectProvider = conn.GetDialectProvider();

        var rowsAdded = 0;

        using (var dbTrans = conn.OpenTransaction()) {
            foreach (var obj in saveRows) {
                var id = obj.GetId();

                if (id != defaultIdValue && existingRowsMap.ContainsKey(id)) {
                    var updStmt = dialectProvider.ToUpdateRowStatement(obj);
                    updStmt = updStmt.Replace(obj.GetType().Name, tablename.FmtTable());
                    conn.ExecuteSql(updStmt);
                }
                else {
                    if (modelDef.HasAutoIncrementId) {}
                    var stmt = dialectProvider.ToInsertRowStatement(null, obj);

                    stmt = stmt.Replace(obj.GetType().Name, tablename.FmtTable());

                    conn.ExecuteSql(stmt);

                    rowsAdded++;
                }
            }

            dbTrans.Commit();
        }
        return rowsAdded;
    }

【问题讨论】:

    标签: servicestack ormlite-servicestack


    【解决方案1】:

    OrmLite 支持为更新和删除操作指定表名。不幸的是,readme here 中的示例尚未更新。这是必需的格式:

    更新:

    db.UpdateFmt(table: "Person", set: "FirstName = {0}".Fmt("JJ"), where: "LastName = {0}".Fmt("Hendrix"));
    

    删除:

    db.DeleteFmt(table: "Person", where: "Age = {0}".Fmt(27));
    

    您需要的方法可以是found here。您应该能够使用.Exec 来处理读取和插入操作。

    【讨论】:

    • 这在 ServiceStack 3.9.71 中有效。它在 ServiceStack 4.0.6 中不起作用
    • @mnfact 奇怪的是它仍然可以工作。我需要查看最新版本的代码,看看有什么变化。
    • 我也去看看。它很可能只是在转换过程中滑倒了。
    猜你喜欢
    • 1970-01-01
    • 2012-03-13
    • 2015-01-07
    • 2013-08-20
    • 2022-01-23
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    相关资源
    最近更新 更多