• 10-10-2016, 22:56:04
    #1
    "Bir varlık nesnesine IEntityChangeTracker'ın birden çok örneği başvuramaz."

    Arkadaşlar merhaba,

    EF5 kullanarak bir projeye başladım. Baya da yol aldım. Şimdilerde böyle bir hata alıyorum. Birbiriyle 4 tabloya aynı transaction scope içerisinde kayıt eklemeye çalışıyorum. ilk 3 tabloya tekil kayıt atıyorum burada sorun yok ama diğer tabloya aynı anda birden fazla da kayıt atabilmem gerekiyor. List i tek tek eklemeye çalışıyorum bu hatayı veriyor. İnternette bakmadığım makale kalmadı. Ya bulduğum çözüm yollarını uygulayamadım yada başka birşey var.

    Yardımcı olabilecek varsa şimdiden çok teşekkür ederim...
  • 11-10-2016, 00:57:50
    #2
    Kimlik doğrulama veya yönetimden onay bekliyor.
    Birden fazla context'mi yaratıyorsun ve using içerisinde mi? Kodlarını da paylaşabilirsen daha iyi yardım edebiliriz.
  • 11-10-2016, 09:01:04
    #3
    rob33n adlı üyeden alıntı: mesajı görüntüle
    Birden fazla context'mi yaratıyorsun ve using içerisinde mi? Kodlarını da paylaşabilirsen daha iyi yardım edebiliriz.
    kodları akşam paylaşırım ama anlatayım.

    birçok yöntem denedim aslında ama şu anda 2 using içerisinde duruyor. 1. transactionscope diğeri de context i new lediğim. Aynı context ile eklemeye çalışıyorum.
  • 12-10-2016, 08:17:26
    #4
    Kodları görelimde ona göre bişey diyelim.
  • 12-10-2016, 09:04:43
    #5
    public void(tblModel model, tblModelBeden beden, tblModelVaryant varyant, List<tblModelUretimAsama> asamalar)
    {
             using(TransactionScope scp = new TransactionScope())
             {
                        using(var dc= new UretimEntities())
                        {
                                   dc.tblModel.Add(model);
                                   
                                   beden.ModelID = model.ID;
                                   dc.tblModelBeden.Add(beden);
    
                                   varyant.ModelID = model.ID;
                                   dc.tblModelVaryant.Add(varyant);
    
                                   foreach(var e in asamalar)
                                   {
                                           e.ModelID = model.ID;
                                           dc.tblModelUretimAsama.Add(e);
                                   }
    
                                   dc.SaveChanges();
                        }
             }
    }
    
    Not: Kodları göndermeyi unuttum aslında ama o kadar çok bakmıştım ki ezberlemişim. Mantığım bu aşağı yukarı.
  • 12-10-2016, 09:18:50
    #6
    devveloper adlı üyeden alıntı: mesajı görüntüle
    public void(tblModel model, tblModelBeden beden, tblModelVaryant varyant, List<tblModelUretimAsama> asamalar)
    {
             using(TransactionScope scp = new TransactionScope())
             {
                        using(var dc= new UretimEntities())
                        {
                                   dc.tblModel.Add(model);
                                   
                                   beden.ModelID = model.ID;
                                   dc.tblModelBeden.Add(beden);
    
                                   varyant.ModelID = model.ID;
                                   dc.tblModelVaryant.Add(varyant);
    
                                   foreach(var e in asamalar)
                                   {
                                           e.ModelID = model.ID;
                                           dc.tblModelUretimAsama.Add(e);
                                   }
    
                                   dc.SaveChanges();
                        }
             }
    }
    
    Not: Kodları göndermeyi unuttum aslında ama o kadar çok bakmıştım ki ezberlemişim. Mantığım bu aşağı yukarı.
    Aslında bu mantık çok yanlış bir EF kullanımı. Tamamen EF avantajlarından vazgeçip herşeyi kendiniz yapmaya çalışmışsınız. Öncelikle bu tablolar arasındaki ilişkileri kullanarak bu işlemleri neden yapmadınız anlamadım. Bu şekilde bir veriyi çok basitce ekleyebilmeniz gerek. Örnek olarak aşağıdaki kod yeterli olacaktır bunun için.

    public void(tblModel model, tblModelBeden beden, tblModelVaryant varyant, List<tblModelUretimAsama> asamalar)
    {
       using(var db = new UretimEntities())
       {
          model.Beden = beden;
          model.Varyant = varyant;
          model.Asamalar.AddRange(asamalar);
          db.tblModel.Add(model);
          db.SaveChanges();
       }
    }
    Şimdi bu kodda sizin ayrıca bir transaction başlatmanıza gerek yok. Burada Entity Framework kendisi bir transaction içerisinde yapacaktır bu işlemleri.
    EF 5 kullanıyorum demişsiniz ama ben EF 5 kullanırkende bu şekilde yapabiliyordum işlemlerimi. Birde zorunlu bir durum değil ise neden EF 6'ya geçmiyorsunuz?
  • 12-10-2016, 09:36:43
    #7
    EF6 kullandım garip hatalar aldığım için 5 e geçtim. 6 da var mıdır bilmiyorum ama 5 te AddRange operasyonu yok. Yani liste eklemek için bir operasyon yok o yüzden tek tek ekledim.

    Tablolar arasında ilişki var aslında; senin kodlarından anladığım şu ;

    model.Beden = beden; dediğim zaman tblModelBeden tablosuna kayıt atacak mı? ve ModelID si set edilmiş şekilde? çünkü model i eklemeden Id kısmı henüz 0 oluyor bunların hepsini aynı anda yapıyorsa çok iyi. Akşam eve gidince denerim.
  • 12-10-2016, 09:43:03
    #8
    devveloper adlı üyeden alıntı: mesajı görüntüle
    EF6 kullandım garip hatalar aldığım için 5 e geçtim. 6 da var mıdır bilmiyorum ama 5 te AddRange operasyonu yok. Yani liste eklemek için bir operasyon yok o yüzden tek tek ekledim.

    Tablolar arasında ilişki var aslında; senin kodlarından anladığım şu ;

    model.Beden = beden; dediğim zaman tblModelBeden tablosuna kayıt atacak mı? ve ModelID si set edilmiş şekilde? çünkü model i eklemeden Id kısmı henüz 0 oluyor bunların hepsini aynı anda yapıyorsa çok iyi. Akşam eve gidince denerim.
    Öncelikle şunu söyleyeyim. Bu şekilde binlerce kişi ve kurum tarafından bir çok projede kullanılan teknolojiler öyle testler yapılmadan son aşamalar geçilmeden yayına alınmaz. Eğer ki bu teknolojinin stabil hali var mümkün olduğu kadar hızlı bir şekilde yeni sisteme geçilmeli. Hata aldığım için 5 e döndüm demek çok yanlış. Hatayı yapan siz siniz cezayı EF'e kesiyorsunuz Tavsiyem kesinlikle her zaman en son sürümü kullanmanız.

    Daha öncede dediğim gibi bunlar zaten entity framework'ün size sunduğu ve asıl amaçları olan özellikler. Benim dediğim gibi yazarsanız kodunuz evet tblModelBeden tablosuna Id ile birlikte kayıt atacak. Bunu SQL Server Profiler yada ExpressProfiler gibi bir araçla takip edebilirsiniz.

    AddRange metodu yok ise model.Asamalar property'si ne olarak tanımlanmış ona bakmak lazım. EF 6 da koleksiyonlar için ICollection arayüzü ile tanımlanıyor o yüzden AddRange var. Ancak döngü içerisinde eklesenizde olur.
    foreach(var item in asamalar)
    {
       model.Asamalar.Add(item);
    }
    Bu şekilde de yazabilirsiniz farketmez.
  • 12-10-2016, 22:09:04
    #9
    Normalde başlı başına bir fonksiyon olsaydı transaction kullanma derdim ama yazdığın koddan anladığım kadarıyla öncesinde action üzerinden geliyor ve sen fonksiyona yönlendiriyorsun.
    Eğer öyle ise ve action'da var db = new UretimEntities(); kullanmış ve aynı objelerden birisini attach etmişsen fonksiyonda aynı objeyi tekrar attach ettiğin için hata vermesi kaçınılmaz.

    EF5'te AddRange olmadğı için OguzK'nın verdiği ilk kodu kullanamazsın ama ilişkilerin olduğu için ikinci verdiği kod çok daha kullanışlı.

    Bir diğer olasılık ise asamalar kısmı. Foreach ile dönerken muhtemelen asamaların propery'si aynı olduğundan yine context üzerine aynı objeyi attach etmeye çalışıyorsun ve yine changetracker hatası alman kaçınılmaz.

    Eğer kodların tamamını paylaşabilirsen daha net yardımcı oluruz.