![](/img/trans.png)
[英]Entity Framework Auditing using ObjectContext on 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。
堆棧跟蹤器:
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.