我试图将相同的对象(只是更改属性)多次添加到数据库,但问题是在将第一条记录添加到数据库后,记录获取了一个id,而其他记录无法添加。
我的模特:
class MyClass{
int id {set;get;}
string name {set;get;}
string color {set;get;}
//and other properities.
}
我的控制器:
public ActionResult Test(MyClass obj,int Counter){
for(int i=0;i<Counter;i++){
MyClass NewObject=obj;
NewObject.name=obj.name+" "+i.ToString();
Db.MyClass.Add(NewObject);
Db.SaveChanges();
}
}
例如,如果我的对象是:name =&#34; theName&#34 ;; Color =&#34; Red&#34 ;;柜台是3; 所以我的预期输出是:
- 第一条记录:name =&#34; theName 0&#34 ;; Color =&#34; Red&#34 ;;
- 第二条记录:name =&#34; theName 1&#34 ;; Color =&#34; Red&#34 ;;
- 第三条记录:name =&#34; theName 2&#34 ;; Color =&#34; Red&#34;;
但是发生的事情是在添加第一条记录之后,NewObject会有一个id,但是obj的问题也是id,尽管我没有将它添加到数据库中! 因此第二条记录将返回错误(&#39;对数据库的更改已成功提交,但更新对象上下文时出错。&#39;)
答案 0 :(得分:1)
您永远不应该使用相同的对象来表示数据库中的多个对象。在引擎盖下,EF保留对它知道的数据对象的引用,这些引用很重要。
如果你想添加很多类似的对象,你可以有多种选择。其中两个是:
使用方法来初始化新对象
您可以使用常用方法初始化对象的多个实例,并仅添加不同的属性值(如果使用C#7,则您的方法也可以是本地函数):
MyClass CreateInstance() {
return new MyClass {
Name = "theName";
Color = "Red";
}
}
public ActionResult Test(MyClass obj, int Counter){
for(int i = 0; i < Counter; i++){
MyClass newObject = CreateInstance();
newObject.Name = newObject.Name + " " + i.ToString();
Db.MyClass.Add(newObject);
Db.SaveChanges();
}
}
使对象可以克隆
您可以使对象可以克隆(您可以实现ICloneable
接口,但这里不需要这个,并且Clone
方法返回object
}:
class MyClass{
public int Id { set; get; }
public string Name { set; get; }
public string Color { set; get; }
public MyClass Clone() {
MyClass clone = (MyClass)MemberwiseClone();
clone.Id = 0;
return clone;
}
}
public ActionResult Test(MyClass obj, int Counter){
for(int i = 0; i < Counter; i++){
MyClass newObject = obj.Clone();
newObject.Name = obj.Name + " " + i.ToString();
Db.MyClass.Add(newObject);
Db.SaveChanges();
}
}
您应该使用哪个选项,完全取决于您的具体用例。
答案 1 :(得分:0)
将复杂对象分配给另一个复合体会导致指向源对象的指针或引用,因此,所做的任何修改都将反映到两个变量引用的一个实例。您可以通过检查对象的哈希代码在.net中看到这一点。要深度克隆或制作副本,您需要使用new MyObject()
在内存中构造一个新对象,然后复制简单类型值。您需要实例化并复制本身就是复杂对象的所有子属性。
public ActionResult Test(MyClass obj,int Counter){
for(int i=0;i<Counter;i++){
MyClass NewObject=new MyClass();
NewObject.name=obj.name+" "+i.ToString();
NewObject.color = obj.color;
Db.MyClass.Add(NewObject);
Db.SaveChanges();
}
}
答案 2 :(得分:0)
一种方法是使用类似的东西构建一个新对象的每个循环迭代(我已经改变了变量名称以匹配更常见的做法):
public ActionResult Test(MyClass baseObj,int Counter){
for(int i=0;i<Counter;i++) {
MyClass newObject = new MyClass()
{
Name = baseObj.Name,
Color = baseObj.Color
};
Db.MyClass.Add(NewObject);
Db.SaveChanges();
}
}
然而,在理想情况下,这将在业务逻辑层中处理以维护Separation of Concerns。使用此方法,在调用添加到数据库的任何方法之前,将构建所有对象。然后,您可以传入List<MyObject>
并在相应的数据图层方法中使用类似Db.MyClass.AddRange(listOfObjectsPassed)
的内容添加列表。