ServiceStack.Ormlite单个poco映射到许多表

时间:2014-01-13 19:22:34

标签: servicestack ormlite-servicestack

我知道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;
    }

1 个答案:

答案 0 :(得分:2)

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

更新:

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

DELETE:

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

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