You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复制现有DbSet实体并修改主键?解决会话线程报错问题

Solution for EF Entity Copy & Primary Key Modification Error

Hey there, let's break down why you're hitting that error and fix it properly—especially since your entity has tons of fields, we'll avoid manually mapping every property!

Why Your Current Code Fails

First, let's look at the root issues:

  1. Reference Assignment: When you do PedidoMassPro_Detail newItem = item;, you're not creating a new entity—you're just pointing newItem to the same object that EF's context is already tracking. Modifying Order_Number here would change the original entity's primary key, which is not what you want.
  2. Delayed Execution + In-Loop SaveChanges: Your Where query returns an IQueryable, which uses lazy loading. When you iterate over it in the foreach, EF is still actively reading from the database. Calling SaveChanges() inside the loop creates a transaction while another thread (the one enumerating the query) is still running in the same session—hence the error.

Fixes That Work (No Manual Property Mapping)

Option 1: Use EF's Built-in Value Cloning

This is the simplest approach if you just need to copy scalar properties (most cases):

// First, materialize the query to a List to avoid lazy loading conflicts
var items = db.PedidoMassPro_Detail.Where(o => o.Order_Number.Equals(orderNumber)).ToList();

foreach(var item in items) {
    // Create a brand new instance of your entity
    PedidoMassPro_Detail newItem = new PedidoMassPro_Detail();
    
    // Copy ALL scalar property values from the original item to the new one
    db.Entry(newItem).CurrentValues.SetValues(item);
    
    // Modify the primary key to your new value
    newItem.Order_Number = "TESTE111";
    
    // Add the new entity to the context
    db.PedidoMassPro_Detail.Add(newItem);
}

// Save all changes at once (better performance + avoids session conflicts)
db.SaveChanges();
  • SetValues() automatically copies every scalar property (like strings, numbers, dates) from the original entity to the new one—no need to write newItem.Field1 = item.Field1; for every field!
  • Calling ToList() upfront forces EF to load all matching entities into memory immediately, so the enumeration doesn't conflict with the SaveChanges() transaction.

Option 2: Use AutoMapper for Full Property Mapping (Including Navigations)

If your entity has navigation properties you need to copy too, AutoMapper is a great tool:

  1. First, install AutoMapper via NuGet if you haven't already.
  2. Configure the mapper and use it to clone your entity:
// Configure AutoMapper to map your entity to itself
var mapperConfig = new MapperConfiguration(cfg => {
    cfg.CreateMap<PedidoMassPro_Detail, PedidoMassPro_Detail>();
});
var mapper = mapperConfig.CreateMapper();

// Materialize the query to a List
var items = db.PedidoMassPro_Detail.Where(o => o.Order_Number.Equals(orderNumber)).ToList();

foreach(var item in items) {
    // Clone the entire entity (including navigation properties if configured)
    var newItem = mapper.Map<PedidoMassPro_Detail>(item);
    
    // Update the primary key
    newItem.Order_Number = "TESTE111";
    
    db.PedidoMassPro_Detail.Add(newItem);
}

db.SaveChanges();

AutoMapper handles all property mapping automatically, even if you add new fields to your entity later—no need to update your cloning code.

Key Takeaways

  • Always materialize your query with ToList() before modifying/saving entities in a loop to avoid lazy loading conflicts.
  • Never assign an existing tracked entity to a new variable—always create a new instance and copy properties.
  • Batch your SaveChanges() calls (do it once after the loop) instead of calling it inside the loop—this is faster and avoids transaction issues.

内容的提问来源于stack exchange,提问作者Jairo Franchi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:47:26