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; }
}
Entry , which represents an entry in 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 enter 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
you can already see that the property of type Produto
will be null and only the ProdutoId
property will have value .
The AddAsync
method of my service class looks 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 viewer 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,
};
}
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 as AddAsync
of Repository I already get the following error:
Attaching an entity of type 'ControlRoupas.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 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'm inserting an Entry, and the Product property is null, because EntityFramework accuses this error?