Требуется ли перезапуск EF вручную?

Я хочу обновить ссылочные элементы существующего объекта.

Должен ли я писать конкретный код для upsert?

Значение: я должен проверить, обрабатываю ли я существующий ссылочный элемент или новый.

Есть ли другой простой способ сделать это?

Что происходит, если вы выполняете только Save?

  public void SaveCofiguration(MamConfiguration_V1Ui itemUi)
        {
            var itemEf = mMamConfiguration_V1UiToEfConvertor.ConvertToNewEf(itemUi);

            using (var maMDBEntities = new MaMDBEntities())
            {
                IDal<MamConfiguration_V1> mamConfigurationDal = mDalFactory.GetDal<MamConfiguration_V1>(maMDBEntities);

                mamConfigurationDal.Save(itemEf);
            }
        }

         public MamConfiguration_V1 GetById(object id)
        {           
                id.ThrowIfNull("id");

                int configurationId = Convert.ToInt32(id);

                var result =
                    mMaMDBEntities.MamConfiguration_V1.SingleOrDefault(item => item.ConfigurationId == configurationId);

                return result;

        }

       public MamConfiguration_V1 Save(MamConfiguration_V1 item)
        {

                item.ThrowIfNull("item");

                var itemFromDB = GetById(item.ConfigurationId);

                if (itemFromDB != null)
                {
                    UpdateEfItem(itemFromDB, item);

                   // if (mMaMDBEntities.ObjectStateManager.GetObjectStateEntry(itemFromDB).State == EntityState.Detached)
//                    {
  //                      mMaMDBEntities.MamConfiguration_V1.AddObject(itemFromDB);
    //                }

                    // Attached object tracks modifications automatically
                    mMaMDBEntities.SaveChanges();

                    return item;
                }





       private void UpdateEfItem(MamConfiguration_V1 itemFromDb, MamConfiguration_V1 itemFromUi)
            {
                itemFromDb.UpdatedDate = DateTime.Now;

                itemFromDb.Description = itemFromUi.Description;

                itemFromDb.StatusId = itemFromUi.StatusId;

                itemFromDb.Name = itemFromUi.Name;

                itemFromDb.NumericTraffic = itemFromUi.NumericTraffic;

                itemFromDb.PercentageTraffic = itemFromUi.PercentageTraffic;

                itemFromDb.Type = itemFromUi.NumericTraffic;

                foreach (var item in itemFromDb.MamConfigurationToBrowser_V1.ToList())
                {
                    if (itemFromUi.MamConfigurationToBrowser_V1.All(b => b.BrowserVersionId != item.BrowserVersionId))
                    {
                        mMaMDBEntities.MamConfigurationToBrowser_V1.DeleteObject(item);
                    }
                }

                for (int i = 0; i < itemFromUi.MamConfigurationToBrowser_V1.Count; i++)
                {
                    var element = itemFromUi.MamConfigurationToBrowser_V1.ElementAt(i);
                    var item = itemFromDb.MamConfigurationToBrowser_V1.SingleOrDefault(b => b.BrowserVersionId == element.BrowserVersionId);
                    if (item != null)
                    {
                        // copy properties from element to item
                    }
                    else
                    {
                        element.Browser = mMaMDBEntities.Browsers.Single(browserItem =>
                            browserItem.BrowserID == element.BrowserID);

                        //element.MamConfiguration_V1 = itemFromDb;

                        //have also tried: element.MamConfiguration_V1 = null;

                        //element.MamConfiguration_V1Reference = null;

                        itemFromDb.MamConfigurationToBrowser_V1.Add(element);
                    }
                }
            }

Но я бы ожидал, что Save(itemUi) и SaveChanges() будут работать нормально. Нет?

Ответ 1

public void InsertOrUpdate(DbContext context, UEntity entity)
{
    context.Entry(entity).State = entity.Id == 0 ?
                                   EntityState.Added :
                                   EntityState.Modified;
    context.SaveChanges();
}

http://forums.asp.net/t/1889944.aspx/1

Ответ 3

"оптимистичный" подход для простых сценариев (демонстраций)... dbContext.Find() help intellisense подсказывает нам, что он либо извлекает сущность по ключу, если она уже присутствует в текущем контексте, либо запрашивает базу данных, чтобы получить ее... тогда мы знаем, что он существует для добавления или обновления. Я использую EFCore v2.2.0.

  var existing = _context.Find<InventoryItem>(new object[] {item.ProductId});
  if (existing == null) _context.Add(item);
  else existing.Quantity = item.Quantity;
  _context.SaveChanges();

Ответ 4

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

Этот пакет Nuget отлично справляется со своей работой: https://www.nuget.org/packages/FlexLabs.EntityFrameworkCore.Upsert/

Github: https://github.com/artiomchi/FlexLabs.Upsert

Пример:

DataContext.DailyVisits
    .Upsert(new DailyVisit
    {
        UserID = userID,
        Date = DateTime.UtcNow.Date,
        Visits = 1,
    })
    .On(v => new { v.UserID, v.Date })
    .WhenMatched(v => new DailyVisit
    {
        Visits = v.Visits + 1,
    })
    .RunAsync();

Базовый сгенерированный sql делает правильное восстановление.