将多个相同记录添加到数据库

时间:2018-04-25 12:43:07

标签: c# asp.net-mvc

我试图将相同的对象(只是更改属性)多次添加到数据库,但问题是在将第一条记录添加到数据库后,记录获取了一个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;)

3 个答案:

答案 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)的内容添加列表。