/// <summary>
/// 提供數據批量處理的方法。
/// </summary>
public interface IBatcherProvider : IProviderService
{
/// <summary>
/// 將 <see cref="DataTable"/> 的數據批量插入到資料庫中。
/// </summary>
/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
/// <param name="batchSize">每批次寫入的數據量。</param>
void Insert(DataTable dataTable, int batchSize = 10000);
}
一、SqlServer數據批量插入
SqlServer的批量插入很簡單,使用SqlBulkCopy就可以,以下是該類的實現:
/// <summary>
/// 為 System.Data.SqlClient 提供的用於批量操作的方法。
/// </summary>
public sealed class MsSqlBatcher : IBatcherProvider
{
/// <summary>
/// 獲取或設置提供者服務的上下文。
/// </summary>
public ServiceContext ServiceContext { get; set; }
/// <summary>
/// 將 <see cref="DataTable"/> 的數據批量插入到資料庫中。
/// </summary>
/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
/// <param name="batchSize">每批次寫入的數據量。</param>
public void Insert(DataTable dataTable, int batchSize = 10000)
{
Checker.ArgumentNull(dataTable, "dataTable");
if (dataTable.Rows.Count == 0)
{
return;
}
using (var connection = (SqlConnection)ServiceContext.Database.CreateConnection())
{
try
{
connection.TryOpen();
//給表名加上前後導符
var tableName = DbUtility.FormatByQuote(ServiceContext.Database.Provider.GetService<ISyntaxProvider>(), dataTable.TableName);
using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, null)
{
DestinationTableName = tableName,
BatchSize = batchSize
})
{
//循環所有列,為bulk添加映射
dataTable.EachColumn(c => bulk.ColumnMappings.Add(c.ColumnName, c.ColumnName), c => !c.AutoIncrement);
bulk.WriteToServer(dataTable);
bulk.Close();
}
}
catch (Exception exp)
{
throw new BatcherException(exp);
}
finally
{
connection.TryClose();
}
}
}
}
SqlBulkCopy的ColumnMappings中列的名稱受大小寫敏感限制,因此在構造DataTable的時候應請注意列名要與表一致。
以上沒有使用事務,使用事務在性能上會有一定的影響,如果要使用事務,可以設置SqlBulkCopyOptions.UseInternalTransaction。
二、Oracle數據批量插入
System.Data.OracleClient不支持批量插入,因此只能使用Oracle.DataAccess組件來作為提供者。
/// <summary>
/// Oracle.Data.Access 組件提供的用於批量操作的方法。
/// </summary>
public sealed class OracleAccessBatcher : IBatcherProvider
{
/// <summary>
/// 獲取或設置提供者服務的上下文。
/// </summary>
public ServiceContext ServiceContext { get; set; }
/// <summary>
/// 將 <see cref="DataTable"/> 的數據批量插入到資料庫中。
/// </summary>
/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
/// <param name="batchSize">每批次寫入的數據量。</param>
public void Insert(DataTable dataTable, int batchSize = 10000)
{
Checker.ArgumentNull(dataTable, "dataTable");
if (dataTable.Rows.Count == 0)
{
return;
}
using (var connection = ServiceContext.Database.CreateConnection())
{
try
{
connection.TryOpen();
using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand())
{
if (command == null)
{
throw new BatcherException(new ArgumentException("command"));
}
command.Connection = connection;
command.CommandText = GenerateInserSql(ServiceContext.Database, command, dataTable);
command.ExecuteNonQuery();
}
}
catch (Exception exp)
{
throw new BatcherException(exp);
}
finally
{
connection.TryClose();
}
}
}
/// <summary>
/// 生成插入數據的sql語句。
/// </summary>
/// <param name="database"></param>
/// <param name="command"></param>
/// <param name="table"></param>
/// <returns></returns>
private string GenerateInserSql(IDatabase database, DbCommand command, DataTable table)
{
var names = new StringBuilder();
var values = new StringBuilder();
//將一個DataTable的數據轉換為數組的數組
var data = table.ToArray();
//設置ArrayBindCount屬性
command.GetType().GetProperty("ArrayBindCount").SetValue(command, table.Rows.Count, null);
var syntax = database.Provider.GetService<ISyntaxProvider>();
for (var i = 0; i < table.Columns.Count; i++)
{
var column = table.Columns[i];
var parameter = database.Provider.DbProviderFactory.CreateParameter();
if (parameter == null)
{
continue;
}
parameter.ParameterName = column.ColumnName;
parameter.Direction = ParameterDirection.Input;
parameter.DbType = column.DataType.GetDbType();
parameter.Value = data[i];
if (names.Length > 0)
{
names.Append(",");
values.Append(",");
}
names.AppendFormat("{0}", DbUtility.FormatByQuote(syntax, column.ColumnName));
values.AppendFormat("{0}{1}", syntax.ParameterPrefix, column.ColumnName);
command.Parameters.Add(parameter);
}
return string.Format("INSERT INTO {0}({1}) VALUES ({2})", DbUtility.FormatByQuote(syntax, table.TableName), names, values);
}
}
以上最重要的一步,就是將DataTable轉為數組的數組表示,即object[][],前數組的上標是列的個數,後數組是行的個數,因此循環Columns將後數組作為Parameter的值,也就是說,參數的值是一個數組。而insert語句與一般的插入語句沒有什麼不一樣。
② C# datatable的信息怎麼添加到資料庫的表中
軟糖來回答羅。
我這里有個SQL連接資料庫的示例,可以參考下。
publicvoid數據集測試()
{
//(1.連接)建立到資料庫的連接conn
SqlConnectionconn=newSqlConnection();
conn.ConnectionString=@"DataSource=(LocalDB)MSSQLLocalDB;AttachDbFilename=J:資料庫SQLDBNewDB.mdf;IntegratedSecurity=True;ConnectTimeout=5";
//(2.打開)
conn.Open();
string表名="Users";
using(conn)
{
//(3.適配)適配器da和數據集ds
da=newSqlDataAdapter();
ds=newDataSet("DataSet1");
//將DataTable添加到DataSet
ds.Tables.Add(dt);
//將DataSet的修改提交至「資料庫」
=newSqlCommandBuilder(da);
da.Update(ds,dt.TableName);
}
//(6.釋放資源)
conn.Close();
conn.Dispose();
//注意:在修改、刪除等操作中表必須定義主鍵,select的欄位也必須包含主鍵,
//否則會拋出異常「對於不返回任何鍵列信息的SelectCommand,不支持UpdateCommand的動態SQL生成。」
}
上面的dt變數就是你的表,需要給它指定一個TableName名字。
連接字元串需要改成你資料庫的,在伺服器資源管理器>數據連接>屬性頁面>連接字元串
(滑鼠選中然後按Ctrl+C復制)
如滿意,請採納,謝謝。
③ C# 處理DataTable 重復數據
你可以用HashSet<T>來存儲已存在的行 檢索速度會快很多 代碼如下 不知道你的機子什麼配置 我的機子Debug模式100000行數據 用了232毫秒using System;
using System.Data;
using System.Collections.Generic;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataTable dataTable = new DataTable();
dataTable.Columns.AddRange(new DataColumn[] {
new DataColumn("A"),
new DataColumn("B"),
new DataColumn("C"),
new DataColumn("D")
});
for (int i = 0; i < 50000; i++)
{
dataTable.Rows.Add(new object[] { 0, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + i.ToString(), 0 });
dataTable.Rows.Add(new object[] { 0, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + (50000 - i).ToString(), 0 });
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Reset();
stopwatch.Start();
Console.WriteLine("DataTable行數:{0}", dataTable.Rows.Count);
HashSet<string> hash = new HashSet<string>();//.NET 3.0以上使用
//Dictionary<string, int> dic = new Dictionary<string, int>();//.NET 2.0可以用這個
for (int i = 0; i < dataTable.Rows.Count; i++)
{
//if (dic.ContainsKey(dataTable.Rows[i][2] as string))//.NET 2.0
//{
// dic.Add(dataTable.Rows[i][2] as string, 0);
//}
if (!hash.Contains(dataTable.Rows[i][2] as string))
{
hash.Add(dataTable.Rows[i][2] as string);
}
else
{
dataTable.Rows.RemoveAt(i);
i--;
}
}
stopwatch.Stop();
Console.WriteLine("用時:{0}毫秒", stopwatch.ElapsedMilliseconds);
Console.WriteLine("DataTable行數:{0}", dataTable.Rows.Count);
Console.ReadKey();
}
}
}
④ c#中的DataTable如何修改數據類型
很簡單。修改下值就可以。
我想LZ要學會自己思考。我想這個你都沒有思考一看不會就發上來了。我給你寫下如何生成DataTable的步驟。然後自己思考,修改下。
最簡單的方式
DataTable dt=new DataTable("Table1"); //創建數據表
DataColumn dcID=new DataColumn("ID",typeof(int)); //創建ID列
DataColumn dcName=new DataColumn("Name",typeof(string));//創建姓名列
DataColumn dcState=new DataColumn("State",typeof(int));//創建狀態列
//把創建的三列放在DataTable中
dt.Columns.Add(dcID); dt.Columns.Add(dcName);
dt.Columns.Add(dcState);
//創建數據行。
DataRow dr=dt.NewRow();
dr["ID"]=1; dr["Name"]=A; dr["State"]=1;
//把創建的行插入到數據表「Table1」中
dt.Rows.Add(dr);
//如上,這樣就創建了一個如題所示的數據表的過程。
如果你想把bit型轉換為char型。只需要候改下插入的列即可。
如將狀態列改為:
DataColumn dcState=new DataColumn("State",typeof(char)); //此處將其改為Char類型。
//如上所示數據行
DataRow dr=dt.NewRow();
dr["ID"]=1; dr["Name"]=A; dr["State"]="是"; //把State列的值改為"是"或「否」即可。
打了半天,只希望樓主能從中體會如何自定義DataTable。
GoodLuck!!
⑤ C#兩個30萬條紀錄的datatable如何進行快速比較
用 like
這是sql 資料庫里的
不知你的是什麼資料庫。我只知ACC和sql 可以用這句,
比循環比較快,具體自已網路
⑥ C#在datatable中怎麼篩選數據
對DataTable數據各種篩選
篩選一個DataTable的數據,賦值給另外一個DataTable
假設:
有2個DataTable:DataTable A、DataTable B。
要求:
篩選DataTable A中itemType欄位值為book的數據,然後把篩選出來的數據,賦給DataTable B
實現:
(1)方法一:通過 RowFilter 篩選實現
DataView view = new DataView();
view.Table = A;
view.RowFilter = "itemType = 'book'";//itemType是A中的一個欄位
B= view.ToTable();
(2)方法二:通過 Select()篩選
DataRow[] rows = A.Select("itemType = 'book'");
B= A.Clone(); //克隆A的結構
foreach (DataRow row in rows)
{
B.ImportRow(row);//復制行數據
}
註:如果有多個篩選條件的話,可以加 and 或 or。例如: A.Select("itemType = 'book' and a='b' or a='c'");
⑦ 一個200行數據的datatable大概佔用多少內存
太少了,現在的內存都是用G來計算的,200行對它來說太少了!
你可以通過二進制序列化,把你那個datatable序列化到文件裡面,你可以大概知道大小了!
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
DataTable dt = new DataTable();
bf.Serialize(ms, dt);
運行看了看,一個空的DataTable也就930個位元組,在.NET 4.0裡面!
⑧ c#怎樣讀取DataTable中的數據
把數據放入datatable中之後,如何讀取指定行列的數據呢?
我放的不是資料庫中的數據,沒有表頭也不止一列,比如我想找第三行第四列的數據。
現在我已經寫了代碼如下:
try
{
string strConn;
strConn = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source= C:\Users\Administrator\Desktop\cstest.xls;Extended Properties='Excel 8.0;HDR=False;IMEX=1'";
OleDbConnection OleConn = new OleDbConnection(strConn);
OleConn.Open();
String sql = "SELECT * FROM [Sheet1$]";
OleDbDataAdapter OleDaExcel = new OleDbDataAdapter(sql, OleConn);
DataSet OleDsExcle = new DataSet();
OleDaExcel.Fill(OleDsExcle, "Sheet1");
DataTable dt = OleDsExcle.Tables[0];
//這里要怎麼繼續寫下去呢....
label1.Text = ;
OleConn.Close();
}
catch (Exception ex)
{
label1.Text = ex.Message;
}
⑨ C#在datatable中怎麼篩選數據
DataTable可以通過select來篩選數據 datatable.select("");
你的需求貌似需要分組可以用linq
⑩ net(C#)情況下在datatable中實現類似count、group by的數據統計
so easy , 直接用linq, from c in datatable group by c.name select c。