考慮到前端應用往數據庫里面插入數據,可以采用三種方式。
第一種:
直接在程序代碼里面寫入SQL,這種方式處理簡單,然后這種方式的效率很低,因為應用程序每次都需要把SQL傳遞給數據庫服務器,
然后數據庫服務器解析,如果在一個循環內部不斷的使用SQL訪問數據庫,那么需要不斷的解析,因此會消耗很長的時間,同時,使用拼接SQL語句方式實現數據寫入時,
由於SQL語句是動態執行的,所以惡意用戶可以通過拼接SQL的方式實施SQL注入攻擊。
第二種方法: 存儲過程
優點:與SQL語句相比,存儲過程存在很多優勢。存儲過程允許標准組件式編程,能夠實現較快的執行速度,能夠減少網絡流量,而且可被作為一種安全機制來充分利用,存儲過程由於在服務端編譯過了,相比較直接使用SQL的方式,省去了SQL的解析過程,因此有很高的時間效率。
缺點:由於其實現方式是利用數據庫訪問類調用存儲過程,利用循環逐條插入,所以這種方式的效率不高。還有兩個方面是他的可移植性和可擴展性,因為一般大型的Web應用程序都是多Web服務器,然后用雙數據庫服務器做雙機熱備,其中一台開機,但是是閑置的。這里只是解決單點故障的問題,但形成了多Web應用服務器,單數據庫服務器的情況。如果所有的運算都用存儲過程實現,那么會造成數據庫服務器負擔過重。而Web服務器負荷不足的情況,擴展數據庫服務器的話就會非常的麻煩,而且投資較大,程序也需要改。
第三種方式,使用OracleBulkCopy
OracleBulkCopy是ODP.NET中的一個類,是ODP.NET才有的功能。
優點:調用WriteToServer方法,可以快速有效的實現大數據量導入數據庫。OracleBulkCopy支持超大文本的導入,支持從數據中的某一行開始導入,可以決定是否保存數據行號,列映射不區分大小寫,支持導入常量列,支持源列自動檢測,當相同源列導入多目標列時,只分配一次內存,更加節約內存。
OracleBulkCopy使用方法也非常簡單
1. 構造數據表 DataTable dt = new DataTable();
2. 為數據表添加列:
dt.Columns.Add(Mappings.Fields.period_name, typeof(string)); --Mapping.Fields當中記錄了要插入數據表的字段名稱,這里取和數據庫表的名稱一致(不是必要的,以后后面還需要一個DataTable和數據庫表的列名映射)
dt.Columns.Add(Mappings.Fields.ledger_id, typeof(int));
這里需要注意的地方是,一定要加入列的類型,如后面的typeof(int),如果不加入的話,默認列的類型是string,會導致批量插入數據出錯。
3. 為數據表填充數據
foreach (PSGLGEArg rec in records.ApplyRecord)
{
DataRow dr = dt.NewRow();
dr[Mappings.Fields.period_name] = rec.period_name;
dr[Mappings.Fields.ledger_id] = rec.ledger_id;
dt.Rows.Add(dr);
}
4. 構造一個 OracleBulkCopy對象。
OracleBulkCopy bulkCopy = new OracleBulkCopy(connStr, OracleBulkCopyOptions.UseInternalTransaction);
這里需要注意的地方是,connStr是連接字符串,OracleBulkCopy 的連接字符串和普通的Oracle連接字符串之間存在區別。比如不支持:unicode=true.
連接字符串例子: "data source=dev;User Id=dyc;Password=1234;Max Pool Size=100;Min Pool Size=5;"
第二個參數是使用OracleBulkCopy內部的事務,保證數據插入的一致性。
5. 填充OracleBulkCopy對應的表名,和DataTable與數據庫表列的映射關系。
foreach (DataColumn col in dt.Columns)
{
bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
7. 最后一步,把構造的數據表當中的數據寫入到數據庫中。
bulkCopy.WriteToServer(dt);
bulkCopy.Dispose();