所以在使用Entity Framework的ASP.NET MVC应用程序中,我希望能够将现有实体(在这种情况下,PERS936AB_request_original
)复制,更改一些数据,并将新实体保存到数据库。这是我现在拥有的:
var PERS936AB_request_original = db.PERS936AB.Single(r => r.ID == id);
var new_request = DataContractSerialization<PERS936AB>(PERS936AB_request_original);
new_request.Year = currentYear;
db.PERS936AB.AddObject(new_request);
db.SaveChanges();
我从MSDN Forum thread获得的DataContractSerialization
方法。
private static T DataContractSerialization<T>(T obj)
{
DataContractSerializer dcSer = new DataContractSerializer(obj.GetType());
MemoryStream memoryStream = new MemoryStream();
dcSer.WriteObject(memoryStream, obj);
memoryStream.Position = 0;
T newObject = (T)dcSer.ReadObject(memoryStream);
return newObject;
}
当我完成所有这些操作时,我收到以下消息。这条消息很有意义,我只是不知道如何“重置”新实体并给它一个新密钥,而且我的搜索结果毫无结果。
ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法跟踪具有相同对象的多个对象 键。
任何帮助都会很棒,谢谢!
答案 0 :(得分:2)
问题是跟踪了原始对象,因此无法添加它的副本。但是没有必要跟踪原件,因为你没有更新它。所以你必须确保没有跟踪对象。同时,您不需要此序列化步骤。您只需修改原始对象并将其添加到上下文中即可。 EF会将其视为一个全新的实例,并忽略其当前的主键值:
db.ContextOptions.LazyLoadingEnabled = false;
db.PERS936AB.MergeOption = MergeOption.NoTracking;
var new_request = db.PERS936AB.Single(r => r.ID == id);
new_request.Year = currentYear;
db.PERS936AB.AddObject(new_request);
db.SaveChanges();
我确定禁用延迟加载:它可以防止无意中添加嵌套对象。
答案 1 :(得分:0)
您需要将ID更改为0. EF认为它们是完全相同的实体(即使年份不同),因为它会根据对象本身的ID进行检查。将其设置为0将告诉EF它是一个全新的实体。