11.2.15

Oracle Veritabanı İçerisindeki System.InvalidOperationException Hatası ve Çözümü

Geliştirdiğim MVC projelerinde gördüm ki Entity Framework SQL veritabanı ile mükemmel çalışıyor. Doğru veritabanı oluşumunu sağladıktan sonra kaydetme, güncelleme ve silme gibi temel işlemleri EF yardımıyla kolayca yapabiliyoruz. Şu ana kadar bu tür temel işlemler içerisinde sebebini bulamadığım hatalarla karşılaşmamıştım. Ne yazık ki bu mutluluğum EF ile Oracle veri tabanını kullanmaya başladığımda biraz olsun can sıkıcı hale geldi.
Bu yazımda EF ile Oracle veritabanını ilişkilendirdiğimizde, birden fazla kayıt yapmak isterken karşımıza çıkan System.InvalidOperationException hatası ve çözümünü ele alacağım.
Örnek kodumuz;
foreach (var doc in documents)
{
    EkBelge belge = EkBelge(doc);
    context.AddToDocuments(belge);
}
try
{
    context.SaveChanges();
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}
Birden fazla işlemi tek seferde kaydetmek istediğimizde EntityFramework bu kayıt sanki daha kaydetmeden üzerine yazmak istiyormuşçasına davranıyor. Dolayısıyla aşağıdaki hatayı fırlatıyor.
System.InvalidOperationException: The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
Bu hatayı düzeltmek için .edmx dosyasının .xml halini açmamız gerekiyor. Oracle da her ne kadar düzgün bir yapılandırma yapsakta(auto increment, identity, primary key vb.), otomatik id arttırma olayını bazen burada göremeyebiliyor. Vs2012'ye gelen SP1.0 güncellemesiyle düzeldiği söylediyse, daha üst bir sürüm kullanan veya güncelleme yapmayan kişiler için .edmx dosyası içerisinde hatayı aldığımız primary key alanına StoreGeneratedPattern="Identity" özelliğini eklememiz gerekiyor.
<EntityType Name="SECKIN">
          <Key>
            <PropertyRef Name="ID" />
          </Key>
          <Property Name="ID" Type="number" Nullable="false"
              MaxLength="10" StoreGeneratedPattern="Identity"/>                 
 </EntityType>
Hangi alanın identity olacağını belirttiğimiz için EF bunu bilerek hareket ediyor ve ilgili hatayı gideriyor. Yeni bir güncellemeyle düzelene kadar umarım bu tür bir yaklaşım kodunuzda ilerlemenize yardımcı olur.
Bol kodlu günler.