When editing a record and saving for the first time the entityframework performs the update successfully, however when I click again to edit and save the registry I encounter the following error:
Error saving record: Attaching an entity of type 'Project.WebERP.EntityFramework.Entities.Counts.Location.City' failed because another entity of the same type has already the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
What am I doing wrong?
Base Repository
public abstract class RepositorioBase<TEntity> : IRepositorioCRUD<TEntity>, IRepositioSQL<TEntity>
where TEntity : EntityBase
{
public RepositorioBase()
{
_context = new ProjetoContext();
}
ProjetoContext _context;
public long GetNextHandle()
{
var instance = Activator.CreateInstance<TEntity>();
var tabela = instance.GetType().Name.ToUpper();
var handle = _context.Database.SqlQuery<long>("SELECT (COALESCE(MAX(HANDLE),0) + 1) HANDLE FROM " + tabela).ToArray();
return Convert.ToInt64(handle[0]);
}
public long Inserir(TEntity entity)
{
try
{
entity.Handle = GetNextHandle();
_context.Set<TEntity>().Attach(entity);
_context.Entry(entity).State = System.Data.Entity.EntityState.Added;
var erros = _context.GetValidationErrors();
if (erros.Count() > 0)
{
string stringErro = string.Empty;
foreach (var erro in erros)
foreach (var er in erro.ValidationErrors)
stringErro += string.Format(er.ErrorMessage.ToString() + " {0}", Environment.NewLine);
if (!string.IsNullOrEmpty(stringErro))
throw new Exception(stringErro);
}
return _context.SaveChanges();
}
catch (Exception erro)
{
throw new Exception(erro.Message);
}
}
public virtual bool Atualizar(TEntity entity)
{
try
{
_context.Set<TEntity>().Attach(entity);
_context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
var erros = _context.GetValidationErrors();
if (erros.Count() > 0)
{
string stringErro = string.Empty;
foreach (var erro in erros)
foreach (var er in erro.ValidationErrors)
stringErro += string.Format(er.ErrorMessage.ToString() + " {0}", Environment.NewLine);
if (!string.IsNullOrEmpty(stringErro))
throw new Exception(stringErro);
}
_context.SaveChanges();
return true;
}
catch (Exception erro)
{
throw new Exception(erro.Message);
}
}
public bool Deletar(TEntity entity)
{
try
{
_context.Set<TEntity>().Attach(entity);
_context.Entry(entity).State = System.Data.Entity.EntityState.Deleted;
var erros = _context.GetValidationErrors();
if (erros.Count() > 0)
{
string stringErro = string.Empty;
foreach (var erro in erros)
foreach (var er in erro.ValidationErrors)
stringErro += string.Format(er.ErrorMessage.ToString() + " {0}", Environment.NewLine);
if (!string.IsNullOrEmpty(stringErro))
throw new Exception(stringErro);
}
_context.SaveChanges();
return true;
}
catch (Exception erro)
{
throw new Exception(erro.Message);
}
}
public IQueryable<TEntity> GetAll()
{
return _context.Set<TEntity>().AsNoTracking().AsQueryable();
}
public IQueryable<TEntity> Find(System.Linq.Expressions.Expression<Func<TEntity, bool>> where)
{
return _context.Set<TEntity>().AsNoTracking().Where(where).AsQueryable();
}
public TEntity GetByHandle(long handle)
{
return _context.Set<TEntity>().AsNoTracking().FirstOrDefault(x => x.Handle == handle);
}
public IQueryable<TResult> FindSelect<TResult>(Expression<Func<TEntity, TResult>> select, Expression<Func<TEntity, bool>> where)
{
return _context.Set<TEntity>().AsNoTracking().Where(where).Select(select).AsQueryable<TResult>();
}
}
City Registration Form
public partial class FormularioCidade : FormularioBase
{
public FormularioCidade()
{
InitializeComponent();
}
RepositorioBase<Pais> _RepositorioPais = new RepositorioPais();
RepositorioBase<Estado> _RepositorioEstado = new RepositorioEstado();
RepositorioBase<Cidade> _RepositorioCidade = new RepositorioCidade();
public override void LoadFormulario()
{
bsGrid.DataSource = ObterRegistrosParaGrid(x => x.Handle > 0).ToList();
}
public override void BotaoNovo()
{
bsCidade.AddNew();
PopularBSPais();
}
public override void BotaoEditar()
{
PopularBSPais();
PosicionarPais();
PosicionarEstado();
}
private IQueryable<object> ObterRegistrosParaGrid(Expression<Func<Cidade, bool>> where)
{
return _RepositorioCidade.FindSelect(x => new
{
Handle = x.Handle,
Descricao = x.Descricao,
Sigla = x.Sigla,
Estado = x.Estado,
EstadoHandle = x.Estado.Handle,
EstadoDescricao = x.Estado.Descricao,
Pais = x.Estado.Pais,
PaisHandle = x.Estado.Pais.Handle,
PaisDescricao = x.Estado.Pais.Descricao,
DataCadastro = x.DataCadastro,
DataAlteracao = x.DataAlteracao
}, where).AsQueryable();
}
public override void BotaoSalvar()
{
if (State == EntityState.Added)
{
Cidade currentCidade = (bsCidade.Current as Cidade);
Pais currentPais = (bsCidade.Current as Pais);
Estado currentEstado = (bsCidade.Current as Estado);
Cidade cidade = new Cidade();
cidade.Handle = _RepositorioCidade.GetNextHandle();
cidade.Descricao = currentCidade.Descricao;
cidade.Sigla = currentCidade.Sigla;
cidade.Estado = currentEstado;
cidade.EstadoHandle = currentEstado.Handle;
cidade.Estado.Pais = currentPais;
cidade.Estado.PaisHandle = currentPais.Handle;
cidade.DataAlteracao = null;
cidade.DataCadastro = DateTime.Now;
_RepositorioCidade.Inserir(cidade);
var newCidade = ObterRegistrosParaGrid(x => x.Handle == cidade.Handle).FirstOrDefault();
bsGrid.Add(newCidade);
}
else if (State == EntityState.Modified)
{
Cidade currentCidade = (bsCidade.Current as Cidade);
Pais currentPais = (bsPais.Current as Pais);
Estado currentEstado = (bsEstado.Current as Estado);
Cidade cidade = new Cidade();
cidade.Handle = currentCidade.Handle;
cidade.Descricao = currentCidade.Descricao;
cidade.Sigla = currentCidade.Sigla;
cidade.Estado = currentEstado;
cidade.EstadoHandle = currentEstado.Handle;
cidade.Estado.Pais = currentPais;
cidade.Estado.PaisHandle = currentPais.Handle;
cidade.DataAlteracao = DateTime.Now;
cidade.DataCadastro = currentCidade.DataCadastro;
_RepositorioCidade.Atualizar(cidade);
var newCidade = ObterRegistrosParaGrid(x => x.Handle == cidade.Handle).FirstOrDefault();
var indice = bsGrid.IndexOf(bsGrid.Current);
bsGrid.RemoveAt(indice);
bsGrid.Insert(indice, newCidade);
bsGrid.Position = indice;
}
}
public override void BotaoCancelar()
{
PopularCamposCadastro();
}
public override void BotaoExcluir()
{
Cidade cidade = (bsCidade.Current as Cidade);
_RepositorioCidade.Deletar(cidade);
var indice = bsGrid.IndexOf(bsGrid.Current);
bsGrid.RemoveAt(indice);
}
public override void BotaoPesquisar()
{
}
private void bsPais_CurrentChanged(object sender, EventArgs e)
{
long handlePais = (bsPais.Current as Pais).Handle;
PopularBSEstado(handlePais);
}
private void bsGrid_CurrentChanged(object sender, EventArgs e)
{
PopularCamposCadastro();
lblTotalRegistros.Text = string.Format("Registro {0} de {1}", bsGrid.IndexOf(bsGrid.Current) + 1, bsGrid.Count);
}
private void PopularCamposCadastro()
{
if (bsGrid.Current != null)
{
Cidade cidade = (bsGrid.Current as object).ToEntity<Cidade>();
Pais pais = (bsGrid.Current as dynamic).Pais;
Estado estado = (bsGrid.Current as dynamic).Estado;
bsCidade.DataSource = cidade;
bsPais.DataSource = pais;
bsEstado.DataSource = estado;
}
}
private void PopularBSPais()
{
bsPais.DataSource = _RepositorioPais.GetAll().ToList();
}
private void PopularBSEstado(long handlePais)
{
if (handlePais > 0)
{
bsEstado.DataSource = _RepositorioEstado.Find(x => x.PaisHandle == handlePais).ToList();
}
}
private void PosicionarPais()
{
if (bsGrid.Current != null)
{
long handlePais = (bsGrid.Current as dynamic).PaisHandle;
bsPais.Position = (bsPais.IndexOf((bsPais.List as List<Pais>).FirstOrDefault(x => x.Handle == handlePais)));
}
}
private void PosicionarEstado()
{
if (bsGrid.Current != null)
{
long handleEstado = (bsGrid.Current as dynamic).EstadoHandle;
bsEstado.Position = (bsEstado.IndexOf((bsEstado.List as List<Estado>).FirstOrDefault(x => x.Handle == handleEstado)));
}
}
}
Class City
[Serializable]
public class Cidade : EntityBase
{
public override long Handle { get; set; }
public string Descricao { get; set; }
public string Sigla { get; set; }
public long EstadoHandle { get; set; }
public virtual Estado Estado { get; set; }
public override DateTime DataCadastro { get; set; }
public override DateTime? DataAlteracao { get; set; }
}
Fluent API City Class
public class CidadeMap : EntityBaseTypeConfiguration<Cidade>
{
public override void ConfigureTableName()
{
ToTable("CIDADE");
}
public override void ConfigurePrimaryKey()
{
HasKey(x => x.Handle)
.Property(x => x.Handle).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
}
public override void ConfigureForeingKeys()
{
HasRequired(p => p.Estado)
.WithMany(p => p.Cidades)
.HasForeignKey(p => p.EstadoHandle);
}
public override void ConfigureProperties()
{
Property(p => p.EstadoHandle)
.HasColumnName("ESTADOHANDLE")
.IsRequired();
Property(p => p.Descricao)
.IsRequired()
.HasMaxLength(150)
.HasColumnName("DESCRICAO");
Property(p => p.Sigla)
.IsRequired()
.HasMaxLength(3)
.HasColumnName("SIGLA");
}
public override void ConfigureHasMany()
{
}
}