Pergunta

I know that Servicestack.Ormlite is setup to be a 1:1 mapping between poco and database table. I have a situation where I will have groups of tables that are of the same structure and they are created as necessary. I am trying to find a way to be able to do something where I can continue to use the IDbConnection and specify the table name in CRUD operations.

Something like

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

I was easily able to work around to make creating and deleting the tables. I am hoping that I can use of the ExpressionVisitor or something else to help change the table name before it is executed. One of the requirements of the project is that it be database agnostic, which is why I am trying to not manually write out the SQL.

Solutions Here are a couple of functions that I ended up creating if anyone out there wants some more examples.

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;
    }
Foi útil?

Solução

OrmLite supports specifying the table name for Update and Delete operations. Unfortunately the examples in the readme here have yet to be updated. This is the required format:

UPDATE:

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

DELETE:

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

The methods you need can be found here. You should be able to use .Exec to handle reading and insert operations.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top