none
Entity framework kullanarak toplu şekilde güncelleme RRS feed

  • Soru

  • Merhaba. Daha öncede toplu şekilde ekleme ile ilgili soru sormuşdum manesef cevaplayan olmadı onu farklı üsulla (ado net kullanarak) yapdım. İstediyim gibi olmasada. Ama güncelleme işlemi çok önemli kaç gündür uraşdım ama yapamadım bunun için sizlere sormak istedim. Yardımçı olursununz sevinirim.

    Tablo yapısı aşağıdakı gibidir. 

    CREATE TABLE tabloA
    (
    id serial PRIMARY KEY NOT NULL,
    productid int NOT NULL,
    Miktar umeric(6,3) NOT NULL,
    FOREIGN KEY(productid) REFERENCES product(id) on delete cascade on update cascade
    );
    
    
    CREATE TABLE tabloB
    (
    id serial PRIMARY KEY NOT NULL,
    productid int NOT NULL,
    Miktar umeric(6,3) NOT NULL,
    FOREIGN KEY(productid) REFERENCES product(id) on delete cascade on update cascade
    );

    tabloaA dakı verilerin bir kısımı datagridviewde listeleniyor.  Bu listelenen verilere gore tabloB-deki miktar kolonun guncellemem lazım. Bunu nasıl yapa bilirim?

    Bu işlem için tek bir kolonu insert yapa biliyorum ama güncelleme olduğu için (yani ki aynı zamanda şart kısmı olduğundan) yapamadım. 

    private void sifaris_guncelle() { List<int> idProduct = new List<int>(); foreach (DataGridViewRow item in dataGridView1.Rows) { idProduct.Add((int)item.Cells["id"].Value); } İslemYap(idProduct); } } private void İslemYap(List<int> idProduct) { var par = new NpgsqlParameter("liste", NpgsqlDbType.Array | NpgsqlDbType.Integer); par.Value = idProduct; ctx.Database.ExecuteSqlCommand(@"Insert into sifarisler (productid) select * from unnest(array[@liste]); ", par); ctx.SaveChanges(); }

      

    Bu şekilde deniyorum olmuyor yapamıyorum

    private void İslemYap(List<int> idProduct, List<decimal> miq) { var par = new NpgsqlParameter("productid", NpgsqlDbType.Array | NpgsqlDbType.Integer); var par2 = new NpgsqlParameter("miq", NpgsqlDbType.Array | NpgsqlDbType.Numeric); par.Value = idProduct; par2.Value = miq; ctx.Database.ExecuteSqlCommand(@"Update tabloB set miqdar = (select * from unnest(array[@miq])) where productid = (select * from unnest(array[@productid])"); ctx.SaveChanges();





    28 Ocak 2020 Salı 12:47

Yanıtlar

  • Nihat,

    Ne yapmak istediğini tam olarak anlamak mümkün degil. Neden biribirinden bagimsiz iki array ile update yapmaya calisiyorsun ki? Her zaman hataya açık bir durum. Istediklerin A tablosunda varsa basitçe bir update kullan olsun bitsin:

    Update tabloB
    set miqdar = ta.Miqdar
    from tabloA ta 
    where ta.ProductId = tabloB.ProductId;

    Buradaki tablolarda ProductId unique mi? Degilse garip bir update olur (olmaz demek daha doğru), neden hem Id hem ProductId var? ProductId zaten primary key degil mi?



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.

    28 Ocak 2020 Salı 13:21
    Yanıtlayıcı
  • Yazarsin, sp yazmadan da yazarsın ya, ben hala bu isi iki adet bagimsiz array ile yapmanın mantiğini anlamış degilim (kodun yanlış olması bir yana).

    Isini saglam kazığa bağla, postgreSQL'e veriyi productid, miqdar seklinde gönder, orada tek bir update ... from ... where calissin.

    postgreSQL'e tek parca veri göndermenin guzel yollarından birisi, veriyi JSON olarak göndermek. postgreSQL JSON veriyi islemek icin tonlarca fonksiyona sahip ve bu isi kolay yapıyor. Senin kodunu baz alarak orneklersek:

    private void sifaris_gonder()
    {
    	Dictionary<int,decimal> miqdarlar = new Dictionary<int,decimal>();
    	foreach (DataGridViewRow item in dataGridView2.Rows)
    	{
    		if (item.Cells["id_product"].Value != null &&
    			item.Cells["simdikiMiktar"].Value != null)
    		{
    			miqdarlar.Add(
    			(int)item.Cells["id_product"].Value,
    			(decimal)item.Cells["simdikiMiktar"].Value);
    		}
    	}
    	CedveleKocur(miqdarlar);
    }
    
    
    private void CedveleKocur(Dictionary<int, decimal> miqdarlar)
    {
    	var sql = @"with data as (
    		            select ProductID, Miqdar from
                           jsonb_to_recordset(@json::jsonb) as 
    					   details (ProductId int, Miqdar decimal)
    					)
    					update Stok
    					set Miqdar = data.Miqdar
    					from data
    					where data.ProductId = Stok.ProductId;";
    	var json = JsonConvert.SerializeObject(
    			   miqdarlar.Select(s => new { productid = s.Key, miqdar = s.Value }));
    	var par = new NpgsqlParameter("@json", NpgsqlDbType.Jsonb);
    	par.Value = json;
    	ctx.Database.ExecuteSqlCommand(sql, par);
    }



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.

    28 Ocak 2020 Salı 16:46
    Yanıtlayıcı
  • postgreSQL'in fonksiyonlarını öğrenmenin yolu bu degil bence ama madem yapmak istiyorsun, ve madem düz SQL yerine plpgSQL ile yapmak istiyorsun:

    CREATE OR REPLACE FUNCTION transfer(_id integer[], _say numeric[])
        returns TABLE
                (
                    productid int,
                    miqdar    numeric
                )
        LANGUAGE plpgsql
    AS
    $$
    BEGIN
        return query
            with ids (productId, id) as (
                select v, row_number() over (order by 1)
                from unnest(_id) t(v)
            ),
                 miqdars (miqdar, id) as (
                     select v, row_number() over (order by 1)
                     from unnest(_say) t(v)
                 ),
                 id_miqdar as (
                     select ids.productId, miqdars.miqdar
                     from ids
                              inner join miqdars on ids.id = miqdars.id
                 ),
                 updatedStok as
                     (
                         UPDATE stok
                             SET miqdar = im.miqdar
                             from id_miqdar im
                             WHERE stok.productid = im.productId
                             returning stok.productid, stok.miqdar)
            select us.productid, us.miqdar
            from updatedStok us;
    END;
    $$;



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.


    29 Ocak 2020 Çarşamba 11:45
    Yanıtlayıcı

Tüm Yanıtlar

  • Nihat,

    Ne yapmak istediğini tam olarak anlamak mümkün degil. Neden biribirinden bagimsiz iki array ile update yapmaya calisiyorsun ki? Her zaman hataya açık bir durum. Istediklerin A tablosunda varsa basitçe bir update kullan olsun bitsin:

    Update tabloB
    set miqdar = ta.Miqdar
    from tabloA ta 
    where ta.ProductId = tabloB.ProductId;

    Buradaki tablolarda ProductId unique mi? Degilse garip bir update olur (olmaz demek daha doğru), neden hem Id hem ProductId var? ProductId zaten primary key degil mi?



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.

    28 Ocak 2020 Salı 13:21
    Yanıtlayıcı
  • Abi asıl tablolar bu şekilde. stok tablosundakı miktar kolonunda olan deyerleri  detail tablosundakı ( belirli bir şarta secilmiş) 'simdikiMiktar' kolonundakı deyerlerle toplu şekilde eslestirmek istiyorum 

    CREATE TABLE product
    (
    id serial PRIMARY KEY NOT NULL,
    barcode varchar(50) UNIQUE NOT NULL,
    productname varchar(50) UNIQUE NOT NULL
    );
    
    CREATE TABLE stok
    (
    id serial PRIMARY KEY NOT NULL,
    productid int UNIQUE NOT NULL,
    miqdar numeric(6,3) NOT NULL,
    alis numeric(6,3) NOT NULL,
    FOREIGN KEY(productid) REFERENCES product(id) on delete cascade on update cascade
    );
    
    
    CREATE TABLE detail
    (
    id serial PRIMARY KEY NOT NULL,
    productid int NOT NULL,
    miqdarSimdiki numeric(6,3) NOT NULL,
    FOREIGN KEY(productid) REFERENCES product(id) on delete cascade on update cascade
    );
     private void sifaris_gonder()
            {
                List<int> idProduct = new List<int>();
                List<decimal> sonMiqdar = new List<decimal>();
                foreach (DataGridViewRow item in dataGridView2.Rows)
                {
                    idProduct.Add((int)item.Cells["id_product"].Value);
                    sonMiqdar.Add((decimal)item.Cells["simdikiMiktar"].Value);
                }
                CedveleKocur(idProduct, sonMiqdar);           
            }
    
    
      private void CedveleKocur(List<int> idProduct, List<decimal> miq)
            {
                var par = new NpgsqlParameter("productid", NpgsqlDbType.Array | NpgsqlDbType.Integer);
                var par2 = new NpgsqlParameter("miq", NpgsqlDbType.Array | NpgsqlDbType.Numeric);
                par.Value = idProduct;
                par2.Value = miq;
    
                ctx.Database.ExecuteSqlCommand(@"Update stok set miqdar = (select * from unnest(array[@miq])) where productid = (select * from unnest(array[@productid])");
    
              
    
    
    
                ctx.SaveChanges();


    Adam mağazada ürünleri sayıyor proqrama detail tablosuna giriyor. Sonra proqramdakı stok tablosundakı miktarla aynı mi diyilmi bulmak için. İşlem tam bitdikden sonra stok tablosundakı miktar kolunun detail tablosundakı simdikiMiktar kolonunile eşleşdirmesi lazım. O yüzden toplu şekilde update yapmalıyım 

    28 Ocak 2020 Salı 13:30
  • Ne farkettigini anlamadım, tablo isimlerini değiştirerek ayni şey degil mi.

    Not: Bir degeri iki yerde tutuyorsan (redundancy), er ya da geç birisi basına dert acabilir.



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.

    28 Ocak 2020 Salı 14:15
    Yanıtlayıcı
  • Abi sag olun uyarınız için ama o kısmı sorun diyil.

    Bu işlemi stored procedure yazarak yapa bilirmiyim?

    CREATE OR REPLACE PROCEDURE transfer(_id integer[],_say numeric[])
    LANGUAGE plpgsql    
    AS $$
    BEGIN
        UPDATE stok 
        SET miqdar =  (select v from unnest(_say) t(v))
        WHERE productid = (select v from unnest(_id) t(v));  
        COMMIT;
    END;
    $$;

    28 Ocak 2020 Salı 14:50
  • Yazarsin, sp yazmadan da yazarsın ya, ben hala bu isi iki adet bagimsiz array ile yapmanın mantiğini anlamış degilim (kodun yanlış olması bir yana).

    Isini saglam kazığa bağla, postgreSQL'e veriyi productid, miqdar seklinde gönder, orada tek bir update ... from ... where calissin.

    postgreSQL'e tek parca veri göndermenin guzel yollarından birisi, veriyi JSON olarak göndermek. postgreSQL JSON veriyi islemek icin tonlarca fonksiyona sahip ve bu isi kolay yapıyor. Senin kodunu baz alarak orneklersek:

    private void sifaris_gonder()
    {
    	Dictionary<int,decimal> miqdarlar = new Dictionary<int,decimal>();
    	foreach (DataGridViewRow item in dataGridView2.Rows)
    	{
    		if (item.Cells["id_product"].Value != null &&
    			item.Cells["simdikiMiktar"].Value != null)
    		{
    			miqdarlar.Add(
    			(int)item.Cells["id_product"].Value,
    			(decimal)item.Cells["simdikiMiktar"].Value);
    		}
    	}
    	CedveleKocur(miqdarlar);
    }
    
    
    private void CedveleKocur(Dictionary<int, decimal> miqdarlar)
    {
    	var sql = @"with data as (
    		            select ProductID, Miqdar from
                           jsonb_to_recordset(@json::jsonb) as 
    					   details (ProductId int, Miqdar decimal)
    					)
    					update Stok
    					set Miqdar = data.Miqdar
    					from data
    					where data.ProductId = Stok.ProductId;";
    	var json = JsonConvert.SerializeObject(
    			   miqdarlar.Select(s => new { productid = s.Key, miqdar = s.Value }));
    	var par = new NpgsqlParameter("@json", NpgsqlDbType.Jsonb);
    	par.Value = json;
    	ctx.Database.ExecuteSqlCommand(sql, par);
    }



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.

    28 Ocak 2020 Salı 16:46
    Yanıtlayıcı
  • Her zaman ki gibi detaylı ve mantıklı öneriniz için size çok teşekkür ediyorum Cetin abi.

    Abi tam benim istediyim işimi yaradı çok sağ olun.

    Öyrenmem amaclı soruyorum bunu  direkt postgrsql -in kendisinden function kullanarak nasıl yaza bilirim?

    CREATE OR REPLACE FUNCTİON transfer(_id integer[],_say numeric[])
    LANGUAGE plpgsql    
    AS $$
    BEGIN
        UPDATE stok 
        SET miqdar =  (select v from unnest(_say) t(v))
        WHERE productid = (select v from unnest(_id) t(v));  
        COMMIT;
    END;
    $$;

    29 Ocak 2020 Çarşamba 07:08
  • postgreSQL'in fonksiyonlarını öğrenmenin yolu bu degil bence ama madem yapmak istiyorsun, ve madem düz SQL yerine plpgSQL ile yapmak istiyorsun:

    CREATE OR REPLACE FUNCTION transfer(_id integer[], _say numeric[])
        returns TABLE
                (
                    productid int,
                    miqdar    numeric
                )
        LANGUAGE plpgsql
    AS
    $$
    BEGIN
        return query
            with ids (productId, id) as (
                select v, row_number() over (order by 1)
                from unnest(_id) t(v)
            ),
                 miqdars (miqdar, id) as (
                     select v, row_number() over (order by 1)
                     from unnest(_say) t(v)
                 ),
                 id_miqdar as (
                     select ids.productId, miqdars.miqdar
                     from ids
                              inner join miqdars on ids.id = miqdars.id
                 ),
                 updatedStok as
                     (
                         UPDATE stok
                             SET miqdar = im.miqdar
                             from id_miqdar im
                             WHERE stok.productid = im.productId
                             returning stok.productid, stok.miqdar)
            select us.productid, us.miqdar
            from updatedStok us;
    END;
    $$;



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.


    29 Ocak 2020 Çarşamba 11:45
    Yanıtlayıcı
  • Ya ben de postgreSQL'in yeteneklerini hep unutup, sanki SQL Server filan kullaniyormus gibi yazıyorum :( Aslında daha kısa ve basit:

    CREATE OR REPLACE FUNCTION transfer(_id integer[], _say numeric[])
        returns TABLE
                (
                    productid int,
                    miqdar    numeric
                )
        LANGUAGE plpgsql
    AS
    $$
    BEGIN
        return query
            with yeni (productId, miqdar) as (
                select *
                from unnest(_id, _say) t(p, m)
            ),
                 updatedStok as
                     (
                         UPDATE stok
                             SET miqdar = im.miqdar
                             from yeni im
                             WHERE stok.productid = im.productId
                             returning stok.productid, stok.miqdar)
            select us.productid, us.miqdar
            from updatedStok us;
    END;
    $$;

    Daha da basit:

    CREATE OR REPLACE FUNCTION transfer(_id integer[], _say numeric[])
        returns table
                (
                    productId int,
                    miqdar    numeric
                )
    AS
    $$
    UPDATE stok
    SET miqdar = t.miqdar
    from unnest(_id, _say) t(productid, miqdar)
    WHERE stok.productid = t.productId
    returning stok.productid, stok.miqdar;
    $$
        language SQL;



    How to create a Minimal, Reproducible Example
    The way to Go.
    World's most advanced open source (object-) relational Database.
    Flutter (for mobile, for web & desktop.


    29 Ocak 2020 Çarşamba 14:23
    Yanıtlayıcı