2014-01-13 32 views
3

我知道Servicestack.Ormlite設置爲poco和數據庫表之間的1:1映射。我有一種情況,我將擁有相同結構的表組,並根據需要創建它們。我試圖找到一種方法來做一些事情,我可以繼續使用IDbConnection並在CRUD操作中指定表名。ServiceStack.Ormlite將單個poco映射到很多表

喜歡的東西

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; 
    } 

回答

2

OrmLite支持爲更新和刪除操作指定表名。不幸的是,readme here中的示例尚未更新。這是需要的格式:

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)); 

你需要可以found here的方法。您應該能夠使用.Exec來處理讀取和插入操作。

+0

這可以在ServiceStack 3.9.71中工作。它不能在ServiceStack 4.0.6 –

+0

@mnfact這很奇怪,它應該仍然工作。我需要看看代碼的最新版本,看看有什麼變化。 – Scott

+0

我也來看看吧。機會只是通過轉換而下滑。 –