Birden fazla kayıt insert veya update edilecekse çoğunlukla bunu bir döngü ile yaparız. Fakat kayıt sayısı eğer çok fazla ise, örneğin 10 bin kaydın insert ve update’i gerekiyorsa o zaman bu performans anlamında büyük bir sıkıntı oluşturmakta. Fakat batch insert kullanılarak bu performans sorunu ortadan kaldırıabilir. Bir projede gerek duyduğumuz bir durum için adım adım aşağıdaki gibi sorunu çözdük.
1- Batch insert’ü gerçekleştirecegimiz tablo aşağıdaki gibi üç alana sahip bir tablo.
2- Tablomuz ile veri tipine ait bir tablo tipi tanımlıyoruz. (user-define table types sekmesinde tüm tanımlı tablo tipleri görülebilir. )
3- Yukarıda tanımladığımız tablo tipini parametre olarak kabul eden sp’mizi de aşağıdaki gibi şekillendiriyoruz.
Tablo, store procedure ve type'ı aşağıdaki gibi oluştu.
Buna kaşılık UI'dan örnek olarak 10000 kayıtlı bir liste gönderelim. Bunun için aşağıdaki kodu kullanabiliriz.
Bir console application açarak aşağıdaki gibi kodlayabiliriz.
class Program { static void Main(string[] args) { List<IncomingFile> inFileList = new List<IncomingFile>(); for (int i = 0; i < 10000; i++) { IncomingFile inFile = new IncomingFile(); inFile.FileName = String.Format("{0}.File", i.ToString()); inFile.Password = String.Format("{0}", i.ToString()); inFile.BusinessDate = DateTime.Now; inFileList.Add(inFile); } IncomingFile.InsertAll(inFileList); } } class IncomingFile { public string FileName { get; set; } public string Password { get; set; } public DateTime BusinessDate { get; set; } public static void InsertAll(List<IncomingFile> contractList) { SqlConnection con = new SqlConnection(); con.ConnectionString = "server=BTUGUNSALNB\\UNSAL;database=BLOG;Trusted_Connection=true"; SqlCommand command = new SqlCommand(); //Çalıştıracağımız command'in Store Procedure olduğunu belirtiyoruz.
command.CommandType = CommandType.StoredProcedure; command.CommandText = "ART.ins_InComingFileBatch"; command.Connection = con; var dtContractList = GenerateIncomingFileListTable(contractList); // Parameters SqlParameter parameter = new SqlParameter(); parameter.ParameterName = "IncomingFileList"; parameter.SqlDbType = SqlDbType.Structured; parameter.TypeName = "ART.TypeIncomingFileList"; parameter.Direction = ParameterDirection.Input; parameter.Value = dtContractList; command.Parameters.Add(parameter); if (con.State != ConnectionState.Open) con.Open(); try { int result = command.ExecuteNonQuery(); } catch (SqlException ex) { throw ex; } } private static DataTable GenerateIncomingFileListTable(List<IncomingFile> IncomingFileList) { DataTable valueTable = new DataTable(); valueTable.Columns.Add("FileName", typeof(string)); valueTable.Columns.Add("Password", typeof(string)); valueTable.Columns.Add("BussinessDate", typeof(DateTime)); if (IncomingFileList != null) { foreach (var item in IncomingFileList) { DataRow dr = valueTable.NewRow(); dr["FileName"] = item.FileName; dr["Password"] = item.Password; dr["BussinessDate"] = item.BusinessDate; valueTable.Rows.Add(dr); } } return valueTable; } }
Sonuc olarak, tek bir transaction ile 10000 kaydı database' göndererek insert ediyoruz.