SqlBulkCopy İle Veri Kopyalama

10 Eylül Cuma, 2010 | Ado.Net Sql /*Yorumlar(0)*/

Excel yada benzeri bir kaynaktan elde ettiğimiz yaklaşık bir milyon kayıt içeren bir DataTable olduğunu düşünelim. Bu kayıtları veritabanında ki x bir tabloya nasıl eklerizinsert?

Tek tek Insert yapmak mı? Bildiğin intihar olur.
DataAdapter ile UpdateGüncelleme yapmak mı? İnanılmaz zahmetli ve gereksiz.(Çalışacağından emin bile değilim)

Biri Bulk Insert mü dedi, işte aradığımız cevap.
Bulk Insert, yüklü miktarda ki verileri herhangi bir tablotableya performanslı bir şekilde eklemek için veri katmanında kullanabileceğimiz bir komuttur. Ado.Net teknolojisi SqlBulkCopy (kısaca sbc diyelim) nesnesi ile bu komutu kolaylıkla kullanmamıza olanak verir.
Tabi kullanımı bu kadar kısıtlamamak gerekir. Sbc ile iki farklı sunucu yada aynı sunucu içinde iki farklı tablo da kopyalanabilir.

Bir örnek ile açıklayalım;
Excel dosyasındaki verileri DataTable nesnesine dolduracağız. Peşinde sbc ile DataTable içindeki verileri örnek bir tabloya ekleyeceğiz.

Örnek Excel dosyası
Excel

Hedef tablo
Table

Excel dosyasındaki alanlar ile tablo alanfieldlarını bilerek farklı isimlendirdim. Sbc nesnesinin bir özelliği de bu gibi durumlarda alanları adresleyebilmesidirmapping.

//Excel -> DataTable
string SourceConnStr =
    "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\data.xls;Extended 
 Properties=\"Excel 8.0;HDR=Yes;IMEX=1\";";
DataTable SourceDT = null;
using (OleDbConnection SourceConn = new OleDbConnection(SourceConnStr))
{
    using (OleDbDataAdapter SourceDAP = new OleDbDataAdapter(
        "select * from [Contact]", SourceConn))
    {
        SourceDT = new DataTable("Contact");
        SourceDAP.Fill(SourceDT);
    }
}
 
//DataTable -> Sql
using (SqlConnection DestinationConn = new SqlConnection(
    "Data Source=.;Initial Catalog=Ordek;Integrated Security=True"))
{
    DestinationConn.Open();
    using (SqlBulkCopy SBC = new SqlBulkCopy(DestinationConn))
    {
        //Verilerin kopyalanacağı Tablo Adı
        SBC.DestinationTableName = "Kisiler";
        //Kaynak ile hedef alanlarının adları farklı ise
        //alanları adreslemek gerekir
        SBC.ColumnMappings.Add("ContactID", "ID");
        SBC.ColumnMappings.Add("FirstName", "Ad");
        SBC.ColumnMappings.Add("LastName", "Soyad");
        SBC.ColumnMappings.Add("EmailAddress", "Email");
        SBC.ColumnMappings.Add("Phone", "Telefon");
        //son olarak WriteToServer metotu ile kaynak hedefe kopyalanır
        SBC.WriteToServer(SourceDT);
        //DataTable dışında DataRow koleksiyonu yada DataReader nesnesi de
        //parametre olarak verilebilir.
    }
}

Örnek proje.

Visual Studio Klavye Kısayolu

3 Eylül Cuma, 2010 | Genel Visual Studio /*Yorumlar(2)*/

Herhangi bir text (cs,sql gibi) ortamında çalışırken Ctrl+U klavye kısayolunu ile seçili tüm karakterleri küçük harfe çevirebilirsiniz.

Güncelleme: Ctrl + Sfth + U ile de büyük harfe çevirebilirsiniz.

Metot Geri Dönüşleri Üzerine

23 Haziran Çarşamba, 2010 | C# /*Yorumlar(1)*/

Metotlar geriye değer döndürür yada döndürmez. Peki döndürenler kaç değer döndürür denildiğinde tabi ki bir deriz. Birden fazlaya ihtiyaç varsa ne yaparız?
Bunun için 3 metot prototipi yazdım, paylaşıyorum.

class Program
{
    static void Main(string[] args)
    {
        //1. yöntemin kullanımı
        int a, b;
        a = Yontem1(out b);
        // sonuc
        //a -> 20 ve b -> 10 olur.
    }
 
    //1. yöntem -> out kullanımı
    static int Yontem1(out int par)
    {
        par = 10;
        return 20;
    }

 İlk yöntem out parametre anahtarını kullanmak. Geriye dönmediği kesin ama metottan etkilendiğide bir gerçek. İşe yarıyor mu, evet :)

class Program
{
    static void Main(string[] args)
    {
        //2. yöntemin kullanımı
        DonenTip tip = Yontem2();
        //sonuc
        //tip.a -> 20 ve tip.b -> 10 olur.
    }
 
    //2. yöntem -> sınıf(class) kullanmak
    class DonenTip
    {
        public int a, b;
    }
 
    static DonenTip Yontem2()
    {
        DonenTip tip = new DonenTip();
        tip.a = 20;
        tip.b = 10;
        return tip;
    }

İkinci yöntem ise Classnesne (Custom Reference Type) kullanmak. Geriye yine tek bir nesne dönüyor. İçsel olarak genişletilebilmesi (property, field) sayesinde çok kullanışlı lakin yazması zahmetli.

class Program
{
    static void Main(string[] args)
    {
        //3. yöntemin kullanımı
        var sonuc = Yontem3();
        //sonuc.Item1 -> 20 ve sonuc.Item2 -> 10 olur.
    }
 
    //3. yöntem Tuples kullanımı
    static Tuple<int, int> Yontem3()
    {
        return Tuple.Create(20, 10);
    }

Son yöntem aslında yazının amacı ve Framework 4.0 yeniliği olan Tupleçok-ögeli kullanmak...

Örnek proje.

ConfigSource İle Daha Düzenli Web.Config

28 Nisan Çarşamba, 2010 | Asp.net /*Yorumlar(1)*/

Web.config dosya tanımlamalarında bulunan configSource özelliği ile verileri birden fazla dosyaya dağıtarak yönetimi daha rahat bir hale getirebiliriz.
ConfigSource
Burada dikkat edilmesi gereken nokta;
yeni eklenen config dosyasında xml bildirimi ve configuration kök düğümünün olmaması gerekir.

Web.config dosyası. configSource ile diğer config dosyalarını kendine bağlıyor.

<?xml version="1.0"?>
<configuration>
    <appSettings configSource="Applications.config"/>
    <connectionStrings configSource="Connections.config"/>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
</configuration>

Tüm appSettings değerleri Applications.config dosyasında.

<appSettings>
    <add key="SendMail" value="True"/>
    <add key="ErrorMessage" value="Hata Oluştu."/>
    <add key="LogOffPath" value="~/Logoff.aspx"/>
    <add key="Logo" value="~/Images/NWTraders.png"/>
</appSettings>

Tüm connectionStrings ifadeleri Connections.config dosyasında.

<connectionStrings >
    <clear/>
    <add name="DB1"
         connectionString="Data Source=.;Initial Catalog=db1;Integrated Security=True;"
             />
    <add name="DB2"
         connectionString="Data Source=.;Initial Catalog=db2;Integrated Security=True;"
             />
    <add name="DB3"
         connectionString="Data Source=.;Initial Catalog=db3;Uid=sa;Pwd=123456;"
             />
    <add name="DB4"
         connectionString="Data Source=.;Initial Catalog=db4;Uid=sa;Pwd=123456;"
             />
</connectionStrings>

Örnek proje.

Repeater Kontrolü İle Veri Sıralama

25 Nisan Pazar, 2010 | Asp.net C# Ado.Net /*Yorumlar(0)*/

Repeater, veri kontrolleri içinde en sevdiğimdir. Onu esnek hale getiren basit yapısı da ben en cezbeden özelliğidir. Basit olduğundan dolayı görevi sadece veri göstermek. Peki sıralama yapmak istersek ne yapmalıyız?
Aslında cevap basit;
HeaderTemplate içine LinkButton kontrolü yerleştirip, sıralama bilgilerini de ViewState içinde tutacağız.

Burada tablotable başlıklarına birer LinkButton ve Image kontrolü koyuyoruz. LinkButton sıralama komutunu işlerken, Image kontrolleri de sıralama yapılan satırları işaret edecek.

<HeaderTemplate>
    <table>
        <tr class="head">
            <th style="width: 65%">
                <asp:LinkButton ID="h1" runat="server" Text="Product Name"
                    CommandName="name" CommandArgument="ProductName" />
                <asp:Image ID="ProductName" runat="server" ImageAlign="AbsMiddle" />
            </th>
            <th style="width: 20%">
                <asp:LinkButton ID="h2" runat="server" Text="Unit Price"
                    CommandName="price" CommandArgument="UnitPrice" />
                <asp:Image ID="UnitPrice" runat="server" ImageAlign="AbsMiddle" />
            </th>
            <th style="width: 15%">
                <asp:LinkButton ID="h3" runat="server" Text="Unit Stok"
                    CommandName="stock" CommandArgument="UnitsInStock" />
                <asp:Image ID="UnitsInStock" runat="server" ImageAlign="AbsMiddle" />
            </th>
        </tr>
</HeaderTemplate>

Sıralama sırasından iki adet bilgiye ihtiyaç var. Sıralanacak veri kolonu ve sıralama yönü. Bu bilgileri ViewState içinde saklıyoruz. Kullanım kolaylığı olması için Propertyözellik olarak tanımlıyoruz.

public string SortOrder
{
    get
    {
        if (ViewState["SortOrder"] == null)
            ViewState["SortOrder"] = "Asc";
        return ViewState["SortOrder"].ToString();
    }
    set
    {
        ViewState["SortOrder"] = value;
    }
}
 
public string SortColumn
{
    get
    {
        if (ViewState["SortColumn"] == null)
            ViewState["SortColumn"] = "ProductName";
        return ViewState["SortColumn"].ToString();
    }
    set
    {
        ViewState["SortColumn"] = value;
    }
}

Sıralama komutu için yazılacak Ado.Net kodları.

"Kolon adı parametre olmadığı için String nesnedinin Format metotunu kullandım."

void GetData()
{
    SqlConnection con = new SqlConnection(
        "Data Source=.;Initial Catalog=Northwind;Integrated Security=True");
    string query = string.Format(
        "Select ProductName,UnitPrice,UnitsInStock From Products Order by {0} {1}",
            SortColumn, SortOrder);
    SqlCommand com = new SqlCommand(
        query, con);
    con.Open();
    rpt1.DataSource = com.ExecuteReader();
    rpt1.DataBind();
    con.Close();
}

Uygulama sonunda elde edeceğimiz veri listesi.

Repeater Sort

Kalan detaylara projeyi indirip bakabilirsiniz.

Projeyi indir.