簡體   English   中英

使用實體框架和 PostgreSQL 的 SaveChanges 錯誤

[英]Errors in SaveChanges using entity framework and PostgreSQL

使用下面的代碼,我正在嘗試使用實體框架將新的 object 插入到我的 PostgreSQL 數據庫中:

Class 坎波

public class campo
{
    public int id { get; set; }
    public int id_extrator { get; set; }
    public string nome { get; set; }
    public bool campo_selecionado { get; set; }

}

調用事件:

private void btnSalvarDetalhesExtrator_Click(object sender, EventArgs e)
{
    try
    {
        _campoDal = new CampoDal();
        List<campo> listaCampos = new List<campo>();
        campo dadosCampo;
        for (int a = 0; a < gvCamposExtrator.RowCount; a++)
        {
            dadosCampo = new campo();
            dadosCampo.id_extrator = _idExtrator;
            dadosCampo.nome = (string)gvCamposExtrator.Rows[a].Cells["Nome"].Value;
            dadosCampo.campo_selecionado = (bool)gvCamposExtrator.Rows[a].Cells["Campo_Selecionado"].Value;
            _campoDal.AdicionarCampo(dadosCampo);
        }
    }
}

添加到數據庫

public campo AdicionarCampo(campo dadosCampo)
{
    try
    {
        _dbContext.Campos.Add(new campo
            {
                nome = dadosCampo.nome,
                id_extrator = dadosCampo.id_extrator,
                campo_selecionado = dadosCampo.campo_selecionado
            }
        );
        _dbContext.SaveChanges();
        return dadosCampo;
    }
    catch (Exception ex)
    {
        throw;
    }
}

但是,當我嘗試執行此操作時,會顯示以下錯誤,這類似於 SQLTransaction 的 ZombieCheck。

錯誤 ZombieCheck Npgsql

堆棧跟蹤器:

   em Npgsql.NpgsqlTransaction.CheckReady()
   em Npgsql.NpgsqlTransaction.get_DbConnection()
   em System.Data.Common.DbTransaction.get_Connection()
   em System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Dispose(DbTransaction transaction, DbInterceptionContext interceptionContext)
   em System.Data.Entity.Core.EntityClient.EntityTransaction.Dispose(Boolean disposing)
   em System.Data.Common.DbTransaction.Dispose()
   em System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   em System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
   em System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass148_0.<SaveChangesInternal>b__0()
   em System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute[TResult](Func`1 operation)
   em System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
   em System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions options)
   em System.Data.Entity.Internal.InternalContext.SaveChanges()
   em System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   em System.Data.Entity.DbContext.SaveChanges()
   em ConectorAditi.DAL.Concrete.CampoDal.AdicionarCampo(campo dadosCampo) na C:\Users\Joao Pedro\source\repos\ConectorAditi\ConectorAditi\DAL\Concrete\CampoDal.cs:linha 29

試圖解決這個問題或給出一個臨時解決方案,而不是在 catch 塊中返回一個 throw,我最初沒有在塊中寫任何東西,或者把它返回我試圖添加的 object,就好像它已經工作一樣。

public campo AdicionarCampo(campo dadosCampo)
{
    try
    {
        _dbContext.Campos.Add(new campo
            {
                nome = dadosCampo.nome,
                id_extrator = dadosCampo.id_extrator,
                campo_selecionado = dadosCampo.campo_selecionado
            }
        );
        return dadosCampo;
    }
    catch (Exception ex)
    {
        return dadosCampo;
    }
}

在這個實現中,數據保存在數據庫中,但是在每個循環交互中,SaveChanges 保存新的 object 和那些已經插入的數據,而不是只插入新實例化的 object 的數據。

不知道是不是問題,但是下面的代碼是指數據庫的上下文class

public class ApplicationDataBase : DbContext
{
    private readonly string schema;
    public DbSet<assunto> Assuntos { get; set; }
    public DbSet<atualizacao_campos_realizada> AtualizacoesCamposRealizadas { get; set; }
    public DbSet<campo> Campos { get; set; }
    public DbSet<carga_realizada> CargaRealizadas { get; set; }
    public DbSet<data_base> DataBases { get; set; }
    public DbSet<extrator> Extratores { get; set; }
    public DbSet<tipo_carga> TiposCargas { get; set; }

    public ApplicationDataBase(string schema) : base("dbConectionString")
    {
        this.schema = schema;
    }
    protected override void OnModelCreating(DbModelBuilder builder)
    {
        builder.Conventions.Remove<PluralizingTableNameConvention>();
        Database.SetInitializer<ApplicationDataBase>(null);
        builder.HasDefaultSchema(this.schema);
        base.OnModelCreating(builder);
    }
}

有誰知道我在這個實現中可能出錯的地方,以及在使用 SaveChanges 時如何解決 NpgsqlTransaction 的“ZombieCheck”問題甚至數據重復問題? 我嘗試了一些解決方案和實現,但沒有一個解決了這些情況。

編輯:

作為臨時解決方案,我在 catch 塊中添加了以下行,該行從上下文跟蹤中刪除了添加的實體,通過@Sowmyadhar Gourishetty 的評論找到了這個解決方案:

        catch (Exception ex)
        {
            _dbContext.Entry(dadosCampo).State = EntityState.Detached;

            return dadosCampo;
         }

但是,我仍然沒有找到避免第一張圖片中發布的“ZombieCheck”錯誤的方法,從而阻止它進入 catch 塊。 如果有人可以提供幫助,我將不勝感激。

我認為您的問題可能是 EF 不知道您的主鍵是什么。

嘗試將以下屬性添加到 class campo中的屬性id

[Key]
public int id { get; set; }

此屬性可以在命名空間System.ComponentModel.DataAnnotations中找到。

此外,您不需要創建新實體。 您只需將要傳遞的那個添加到方法中即可。 現在沒有必要退回任何東西。 此外,如果您只是要重新拋出異常,那么捕獲異常是沒有意義的。 唯一有用的是如果您需要添加有關方法內部發生的事情的其他信息。

然后您的方法簡化為:

public void AdicionarCampo(campo dadosCampo)
{
    _dbContext.Campos.Add(dadosCampo);
    _dbContext.SaveChanges();
}

話雖如此,您的代碼目前總是會添加新記錄。 如果您希望更新現有對象並僅添加新對象,那么您需要先從上下文中檢索對象(當它們存在時),更新它們,然后在上下文中調用SaveChanges方法。

我要注意的一件事是您保留了一個內部上下文實例 ( _dbContext )。 這意味着您在使用時需要確保上下文在正確的 state 中。 上下文旨在用作一個工作單元,因此如果您要允許最終將“提交”在一起的一系列操作,則應該僅以這種方式保持它的活動狀態。 事實上,如果這不能解決您的問題,那么您很可能在這些可能導致問題的調用之前對 DAL(以及上下文)進行了其他操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM