Как сохранить модель, которая имеет существующие данные, а также новые данные?

В настоящее время у меня есть модель, которая имеет существующие данные, а также новые данные.

В качестве примера это моя модель

 public class NameDetails
    {
        public int Id { get; set; }
        public string Name { get; set; }

    }

Это данные, которые в настоящее время имеют

  List<NameDetails> Names = new List<NameDetails>{

                new  NameDetails{Id = 1, Name = "Name 1"},
                new NameDetails{Id = 2 , Name = "Name 2"},
            };

Теперь предположим, что мне нужно сохранить это в базе данных. У меня уже есть id = 1 в таблице, поэтому это должно быть обновление, где id = 2 должен быть добавлением... как я могу это сделать

Раньше, когда я записывал сохраненные данные в репозитории, я делал либо добавление, либо редактирование Добавьте так:

 context.NameDetails.Add(NameDetails); 
    context.SaveChanges(); 

или Отредактируйте так,

var recordToUpdate = context.NameDetails.FirstOrDefault(x => x.Id== 1);
recordToUpdate.Name = "New name";
context.SaveChanges();

значит ли это, что мне нужно прокрутить список и выяснить, что нового, а что нет.. или есть другой способ?

Ответ 1

Вы можете использовать некоторые соглашения, которые отлично работают с Entity Framework.

Например, если вы используете IDENTITY(1,1) в своей базе данных (чтобы он автоматически генерировал идентификаторы для вставленных строк), ваше свойство объекта должно использовать StoreGeneratedPattern в качестве Identity (случай первого подхода модели), а ваше свойство Id со значением 0 означает , оно еще не добавлено в базу данных.

Тогда вы можете легко решить, что добавить и что обновить. Вот какой-то псевдо (непроверенный) код:

foreach (var entity in entities)
{
    if (entity.Id == 0)
    {
        // Adds to the context for a DB insert
        context.Entities.Add(entity);
    }
    else
    {
        // Updates existing entity (property by property in this example, you could update
        // all properties in a single shot if you want)
        var dbEntity = context.Entities.Single(z => z.Id == entity.Id);
        dbEntity.Prop1 = entity.Prop1;
        // etc...
    }
}

context.SaveChanges();

Ответ 2

Только EF5 +:

Если у вас есть способ определить, является ли новый элемент (Id == 0 хорош, как и в ответе ken2k), вы можете сделать это, чтобы избежать необходимости сопоставлять вещи:

foreach(var entity in entities)
{
    context.NameDetails.Attach(entity);
    context.Entry(entity).State = IsNewEntity(entity) 
                                  ? EntityState.Added
                                  : EntityState.Modified;
}

Это позволит EntityFramework создать INSERT для новых объектов и UPDATE для старых объектов.

Ответ 3

Попробуйте следующее:

var nameIds = Names.Select(n => n.Id);

var recordsToUpdate = context.NameDetails.Where(x => nameIds.Contains(x.Id));

Ответ 4

Entity Framework не очень хорошо работает в таких ситуациях. Это должно приблизиться к тому, что вы ищете:

public class NameDetails
{
    public int Id {get;set;}
    public string Name {get;set;}
}

List<NameDetails> Names = new List<NameDetails>
    {
        new  NameDetails{Id = 1, Name = "Name 1"},
        new NameDetails{Id = 2 , Name = "Name 2"},
    };


var toFetch = Names.Select(n => n.Id).ToArray();
var association = context.NameDetails
                         .Where(n => toFetch.Contains(n.Id))
                         .ToDictionary(n => n.Id);

foreach(var name in Names)
{
    NameDetails existing;
    if(association.TryGetValue(name.Id, out existing))
    {
        // It exists, map the properties in name to existing
    }
    else
    {
        // It new, perform some logic and add it to the context
        context.NameDetails.Add(name);
    }
}

context.SaveChanges()

В качестве альтернативы вы можете попытаться захватить Entity Framework Migration AddOrUpdate, который выполняет upsert:

// You need a namespace import of  System.Data.Entity.Migrations
context.NameDetails.AddOrUpdate(names.ToArray());
context.SaveChanges();

Я не пробовал это, но он должен работать, если в AddOrUpdate нет дополнительной логики, которая ускользает от меня.