Добавление нескольких одинаковых записей в БД - PullRequest
0 голосов
/ 25 апреля 2018

Я пытаюсь добавить один и тот же объект (просто изменяя свойство) несколько раз в базу данных, но проблема в том, что после добавления первой записи в базу данных запись получает идентификатор, и другие записи не могут быть добавлены.

Моя модель:

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 = "theName"; Color = "Red"; И счетчик 3; Итак, мой ожидаемый результат:

  • Первая запись: name = "theName 0"; Color = "Red";
  • Вторая запись: name = "theName 1"; Color = "Red";
  • Третья запись: name = "theName 2"; Color = "Red";

Но что происходит, когда после добавления первой записи у NewObject будет идентификатор, но у проблемы, которая есть у obj, также есть идентификатор, хотя я не добавил его в базу данных! Таким образом, вторая запись вернет ошибку («Изменения в базе данных были успешно зафиксированы, но произошла ошибка при обновлении контекста объекта.»)

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Присвоение сложного объекта другому сложному приводит к указателю или ссылке на исходный объект, поэтому любые сделанные изменения будут отражать один экземпляр, на который ссылаются две переменные.Вы можете увидеть это в .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();
    }
 }
0 голосов
/ 25 апреля 2018

Один из подходов заключается в создании нового объекта на каждой итерации цикла с чем-то вроде этого (я изменил имена переменных, чтобы они соответствовали более распространенным методам):

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();
    }
 }

Однако в идеальной ситуации это будет обрабатываться на уровне бизнес-логики для поддержки Разделение проблем . При таком подходе построение всех ваших объектов будет происходить до того, как вы вызовете какие-либо методы, добавляемые в базу данных. Затем можно передать List<MyObject> и добавить список, используя что-то вроде Db.MyClass.AddRange(listOfObjectsPassed) в соответствующем методе слоя данных.

0 голосов
/ 25 апреля 2018

Никогда не следует использовать один и тот же объект для представления нескольких объектов в БД. Под капотом 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();
    }
}

Какой вариант вы должны использовать, полностью зависит от вашего конкретного варианта использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...