Asp.net mvc 4 为什么在Entity Framework 6中,当将域模型复制到另一个域模型时,更改副本的值时原始对象会得到更新?
下面是本例所需的模型Asp.net mvc 4 为什么在Entity Framework 6中,当将域模型复制到另一个域模型时,更改副本的值时原始对象会得到更新?,asp.net-mvc-4,entity-framework-6,Asp.net Mvc 4,Entity Framework 6,下面是本例所需的模型 public class OrderDetailPackageVM { public OrderDetail OrderDetail { get; set; } public Package Package { get; set; } } public class Package { public Package() { this.PackageProducts = new List<PackageProduct>
public class OrderDetailPackageVM
{
public OrderDetail OrderDetail { get; set; }
public Package Package { get; set; }
}
public class Package
{
public Package()
{
this.PackageProducts = new List<PackageProduct>();
}
public int PackageId { get; set; }
public int WebsiteId { get; set; }
public virtual List<PackageProduct> PackageProducts { get; set; }
}
public class PackageProduct
{
public int PackageProductId { get; set; }
public int PackageId { get; set; }
public virtual Package Package { get; set; }
public int ProductId { get; set; }
public virtual Product Product { get; set; }
public int ProductCategoryId { get; set; } // not a FK but data only
public virtual ProductCategory ProductCategory { get; set; }
}
在我的手表中,我们看到:
pkgs.Package.PackageProducts.Count = 0;
packages.Package.PackageProducts.Count = 0;
当我期待看到:
pkgs.Package.PackageProducts.Count = 6;
packages.Package.PackageProducts.Count = 0;
那么,当更改应用于副本时,为什么原始对象会更改呢。我不记得早期版本的EF中有这种行为
这方面的工作是什么
我认为使用NoTracking进行选择应该是从EF变更跟踪中“释放”模型中的数据
非常感谢你帮助我理解这种行为
以下是我根据以下反馈解决此问题的方法:
public static T DeepClone<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
不创建新对象。将现有对象放置在新列表中。您需要创建全新的对象并手动复制值。这也称为深度复制或克隆,请参阅 如果omu valueInjector为属性分配属性,则会将对象a的列表分配给对象b的列表。因为它是引用类型,所以实际上是相同的。如果你想拥有新的对象,你必须制作一个深度副本。有关更多信息,请参阅 该行为实际上与从EF视图跟踪更改无关。您可以使用引用类型 一个小样本程序:
using System;
using System.Collections.Generic;
namespace _28637405 {
class Outer {
public string MyProperty { get; set; }
}
class Program {
static void Main( string[] args ) {
var listOne = new List<Outer>();
for ( int i = 0; i < 10; i++ ) {
listOne.Add( new Outer { MyProperty = "obj #" + (i + 1) } );
}
// first line
Console.WriteLine( listOne[0].MyProperty );
var listTwo = new List<Outer>();
listTwo.AddRange( listOne );
// second line
Console.WriteLine( listTwo[0].MyProperty );
listTwo[0].MyProperty = "Changed";
// third and fourth line
Console.WriteLine( listOne[0].MyProperty );
Console.WriteLine( listTwo[0].MyProperty );
var listThree = new List<Outer>();
foreach ( var obj in listOne )
listThree.Add( new Outer { MyProperty = obj.MyProperty } );
listThree[0].MyProperty += " again";
// lines 5,6,7
Console.WriteLine( listOne[0].MyProperty );
Console.WriteLine( listTwo[0].MyProperty );
Console.WriteLine( listThree[0].MyProperty );
}
}
}
如果将实现ICloneable,则类Outer将如下所示:
使用方法包括向外部浇铸:
谢谢你的回复。这绝对有道理,让我走上了正确的道路。虽然我没有使用你的解决方案。我将把分数奖励给你。我编辑了这篇文章以反映我使用的方法。我在这里找到了方法:
public static T DeepClone<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
using System;
using System.Collections.Generic;
namespace _28637405 {
class Outer {
public string MyProperty { get; set; }
}
class Program {
static void Main( string[] args ) {
var listOne = new List<Outer>();
for ( int i = 0; i < 10; i++ ) {
listOne.Add( new Outer { MyProperty = "obj #" + (i + 1) } );
}
// first line
Console.WriteLine( listOne[0].MyProperty );
var listTwo = new List<Outer>();
listTwo.AddRange( listOne );
// second line
Console.WriteLine( listTwo[0].MyProperty );
listTwo[0].MyProperty = "Changed";
// third and fourth line
Console.WriteLine( listOne[0].MyProperty );
Console.WriteLine( listTwo[0].MyProperty );
var listThree = new List<Outer>();
foreach ( var obj in listOne )
listThree.Add( new Outer { MyProperty = obj.MyProperty } );
listThree[0].MyProperty += " again";
// lines 5,6,7
Console.WriteLine( listOne[0].MyProperty );
Console.WriteLine( listTwo[0].MyProperty );
Console.WriteLine( listThree[0].MyProperty );
}
}
}
obj #1
obj #1
Changed
Changed
Changed
Changed
Changed again
class Outer : ICloneable {
public string MyProperty { get; set; }
public object Clone() {
return new Outer { MyProperty = this.MyProperty };
}
}
var newObject = existingObject.Clone() as Outer;