C# 实体框架代码前6个-放置实体状态时出现无效操作异常?可能的EF错误?
我有一个问题,实体框架代码前六个工作如此断开。当我想将一个实体标记为已修改时,就会出现问题,该实体的关联属性加载了一个新的DbContext实例,更准确地说,是命中的来源,然后得到保存C# 实体框架代码前6个-放置实体状态时出现无效操作异常?可能的EF错误?,c#,entity-framework,ef-code-first,code-first,C#,Entity Framework,Ef Code First,Code First,我有一个问题,实体框架代码前六个工作如此断开。当我想将一个实体标记为已修改时,就会出现问题,该实体的关联属性加载了一个新的DbContext实例,更准确地说,是命中的来源,然后得到保存 public List<Venta> Get(Expression<Func<Venta, bool>> predicate) { try { int num = 0; List<V
public List<Venta> Get(Expression<Func<Venta, bool>> predicate)
{
try
{
int num = 0;
List<Venta> ventas = new List<Venta>();
using (_context = new MyContext(MyContext.GetConnectionString()))
{
if (predicate == null)
ventas = _context.Ventas.Include("Mesa").Include("Usuario").Include("Pago").ToList();
else
ventas = _context.Ventas.Include("Mesa").Include("Usuario").Include("Pago").Where(predicate).ToList();
}
//I use the other repo to load related entities
UsuarioRepository userRepo = new UsuarioRepository();
foreach (Venta item in ventas)
{
item.GetType().GetProperty("Usuario").SetValue(item, userRepo.Get(u => u.Id == item.UsuarioId).First(), null);
}
//I use the other repo to load related entities
ProductoRepository prodRepo = new ProductoRepository();
foreach (VentaProducto item in ventas.SelectMany(vta => vta.Detalle).ToList())
{
Producto p = prodRepo.Get(prod => item.ProductoId == prod.Id).First();
item.GetType().GetProperty("Producto").SetValue(item, p, null);
}
ventas.ForEach(vta => vta.State = DomainEntityState.Unchanged);
return ventas;
}
catch (Exception ex)
{
throw new Exception("Error al traer las Ventas", ex);
}
}
public override int Save(Venta venta)
{
int saves = 0;
EntityState state;
EntityState stateProducto;
//New Instance of the context without entities in the DbSet's
using (MyContext context = new MyContext(MyContext.GetConnectionString()))
{
try
{
if (venta.IsNewEntity) //Venta nueva
{
state = EntityState.Added;
stateProducto = EntityState.Modified;
}
else
{
state = EntityState.Modified;
stateProducto = EntityState.Modified;
}
//int usuarios = context.Usuarios.Local.Count; //I get 0
//int productos = context.Productos.Local.Count; //I get 0
//int ventasProductos = context.VentasProducto.Local.Count; // I get 0
venta.Usuario = null;
if (venta.Pago != null)
venta.Pago.Usuario = null;
if (venta.Pago != null)
{
EntityState estadoPago = context.GetEntityState(venta.Pago);
}
//HERE IS THE PROBLEM
context.SetEntityState(venta, state);
saves = context.SaveChanges();
}
catch (Exception ex)
{
throw new Exception("Error al grabar la venta", ex);
}
}
return saves;
}
公共列表获取(表达式谓词)
{
尝试
{
int num=0;
List ventas=新列表();
使用(_context=new MyContext(MyContext.GetConnectionString()))
{
if(谓词==null)
文塔斯=_context.ventas.Include(“Mesa”).Include(“Usuario”).Include(“Pago”).ToList();
其他的
ventas=_context.ventas.Include(“Mesa”).Include(“Usuario”).Include(“Pago”).Where(谓词).ToList();
}
//我使用其他回购来加载相关实体
UsuarioRepository userRepo=新的UsuarioRepository();
foreach(文塔项目在文塔中)
{
item.GetType().GetProperty(“Usuario”).SetValue(item,userRepo.Get(u=>u.Id==item.UsuarioId).First(),null);
}
//我使用其他回购来加载相关实体
ProductoRepository prodRepo=新ProductoRepository();
foreach(ventas.SelectMany(vta=>vta.Detalle.ToList())中的VentaProducto项)
{
Producto p=prodRepo.Get(prod=>item.ProductoId==prod.Id).First();
item.GetType().GetProperty(“Producto”).SetValue(item,p,null);
}
ForEach(vta=>vta.State=DomainEntityState.Unchanged);
回程静脉;
}
捕获(例外情况除外)
{
抛出新异常(“错误al traer las Ventas”,ex);
}
}
公共覆盖整数保存(文塔文塔)
{
int=0;
实体状态;
实体状态状态产品;
//在DbSet中没有实体的上下文的新实例
使用(MyContext context=newmyContext(MyContext.GetConnectionString())
{
尝试
{
if(venta.IsNewEntity)//venta nueva
{
state=EntityState.Added;
stateProducto=EntityState.Modified;
}
其他的
{
state=EntityState.Modified;
stateProducto=EntityState.Modified;
}
//int usuarios=context.usuarios.Local.Count;//我得到0
//int productos=context.productos.Local.Count;//我得到0
//int-ventasProductos=context.VentasProducto.Local.Count;//我得到0
venta.Usuario=null;
if(venta.Pago!=null)
venta.Pago.Usuario=null;
if(venta.Pago!=null)
{
EntityState estadoPago=context.GetEntityState(venta.Pago);
}
//问题就在这里
SetEntityState(venta,state);
saves=context.SaveChanges();
}
捕获(例外情况除外)
{
抛出新异常(“错误al grabar la venta”,ex);
}
}
返回保存;
}
最后我得到以下错误
附加“Jackie.Domain.Entities.Usuario”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”
最奇怪的是,如果我加载具有相同上下文实例的所有实体,就不会有这个问题。那会是一只虫子吗?别再想别的了。谢谢大家。由google translator制作。在对象图中有(至少)两个Usuario
属性-venta.Usuario
和venta.Pago.Usuario
。通过附加venta
实体,这两个Usuario
属性中的实体对象将作为未修改的附加。如果这两个属性包含具有相同PK值的Usuario
类的两个不同实例,则当附加第二个实例时,它将抛出您收到的错误。这似乎很有可能,因为您正在通过上下文的不同实例加载导航属性,并将一些急切的加载抛到混合中
在调用context.SetEntityState(venta,state)
时中断,看看这两个Usuario
对象实际上是同一个实例还是两个具有相同PK值的不同实例。该方法似乎被切成两半,很抱歉我赢得了编辑器,请清理并格式化您的代码。删除无用的注释和调试代码(如“//仅用于监视状态”和其他)-此代码甚至可能导致问题。另外,为什么要显示这个Get
方法?EF中不太可能有bug。您尝试在一个上下文中加载同一个键两次,或者尝试在2个上下文中加载同一个对象实例。我所做的是将实体与上下文一起加载,然后丢弃该上下文,并使用上下文的新实例保存更改。使用相同的PK连接两个实体不是问题,因为我用来记录数据的上下文是一个新实例。谢谢大家的帮助。菲尔,这是问题