2
I have the following classes:
Product:
public class Produto
{
[Key]
public int Id { get; set; }
[MaxLength(70)]
[Required(AllowEmptyStrings = false)]
public string Descricao { get; set; }
[MaxLength(10)]
[Required(AllowEmptyStrings = false)]
public string Tamanho { get; set; }
[Required]
public double Preco { get; set; }
}
Entree, representing an entry into stock:
public class Entrada
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("Produto")]
public int ProdutoId { get; set; }
public virtual Produto Produto { get; set; }
[Required]
[Column(TypeName = "Date")]
public DateTime DataCadastro { get; set; }
[Required]
public int Quantidade { get; set; }
[Required]
public double ValorCompra { get; set; }
[Required]
public double ValorVenda { get; set; }
}
In my controller the Action that receives the post to insert an entry record is like this:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(
[Bind(Include = "Id, ProdutoId, DataCadastro, Quantidade, ValorCompra, ValorVenda")]
EntradaModelEdit model)
{
if (ModelState.IsValid)
{
await _service.AddAsync(model);
return RedirectToAction("Index");
}
return View(model);
}
Only by Bind
in Action
it is already possible to see that the property of type Produto
will stay null and only property ProdutoId
will have value.
The method AddAsync
of my service class is like this:
public async Task AddAsync(EntradaModelEdit model)
{
using (var transaction = _repository.Context.Database.BeginTransaction())
{
try
{
await _repository.AddAsync(EntradaResolver.CreateEntradaFromModel(model));
var produtoService = new ProdutoService(new ProdutoRepository(_repository.Context));
await produtoService.AtualizarPrecoProdutoAsync(model.ProdutoId, model.ValorVenda);
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
throw new Exception(e.Message);
}
}
}
EntradaResolver.CreateEntradaFromModel
is my vision model class mapper for bank entities and vice versa:
public static Entrada CreateEntradaFromModel(EntradaModel obj)
{
if (obj == null)
return null;
return new Entrada
{
Id = obj.Id,
ProdutoId = obj.ProdutoId,
Produto = ProdutoResolver.CreateProdutoFromModel(obj.Produto),
DataCadastro = obj.DataCadastro,
Quantidade = obj.Quantidade,
ValorCompra = obj.ValorCompra,
ValorVenda = obj.ValorVenda,
};
}
That of Product:
public static Produto CreateProdutoFromModel(ProdutoModel obj)
{
if (obj == null)
return null;
return new Produto
{
Id = obj.Id,
Descricao = obj.Descricao,
Tamanho = obj.Tamanho,
Preco = obj.Preco
};
}
And finally, in my repository I have the following in AddAsync
:
public async Task AddAsync(TEntity model)
{
_context.Entry(model).State = EntityState.Added;
await _context.SaveChangesAsync();
}
After executing such lines of AddAsync
of Repository I already get the following error:
Attaching an Entity of type 'Controleroupas.domain.Entity.Product' failed because Another Entity of the same type already has 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 some entities are new and have not yet Received 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.
But I am entering an Input, and the Product property is null, because Entityframework accuses this error?
I think it’s because of
ProdutoId = 1
andProduto = null
. You’ll have to read the Product whose id is 1 assign it toEntrada.Produto
. You also need to ensure that_context.Entry(Produto).State == EntityState.Unchanged
– ramaral
@ramaral, Because it happens, being that it doesn’t always occur, I usually make insertions in this way.
– Severo
So you will need to identify what is different in each of the situations.
– ramaral
@ramaral, Boy, hard sometimes to understand what this business wants. I understood that not.
– Severo