2013-04-24 7 views
10

Chcę wstawić elementy odniesienia istniejącego obiektu.Czy EF wtrąć należy zrobić ręcznie?

Czy muszę napisać konkretny kod dla upsert?

znaczenie: Muszę sprawdzić, czy obsługuję istniejącego elementu referencyjnego lub nowego.

Czy istnieje inny prosty sposób na zrobienie tego?

Co stanie się, gdy wykonasz tylko 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); 
        } 
       } 
      } 

Ale musiałbym expecte Save(itemUi) i SaveChanges() aby działać poprawnie. Nie?

+0

Jedną z możliwości jest zastosowanie unikatowego indeks i do wkładki: 'DbUtils.IgnoreErrors (_db() => DbUtils.InsertEntity (_db, someEntity) DbUtils.IsDuplicateInsertError)' z : http://stackoverflow.com/questions/19042107/handle-exceptions-in-entity-framework-4/34670770#34670770 –

Odpowiedz

18
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

+0

Co stanie się, gdy zrobisz tylko "Save"? –

+0

Mam do czynienia z członkami dla członków nawigacji. Jak można to zrobić? –

+0

To nie jest właściwe dla wspólnego przypadku, gdy tworzysz całą encję - z jej kluczem podstawowym (może być złożony) - i chcesz zaktualizować ten wiersz (jeśli już istnieje w DB) lub chcesz go dodać to jeśli nie. Metoda AddOrUpdate jest lepsza. – AyCabron

3

See 'AddOrUpdate' metoda System.Data.Entity.Migrations.
http://msdn.microsoft.com/en-us/library/system.data.entity.migrations.idbsetextensions.addorupdate%28v=vs.103%29.aspx

using System.Data.Entity.Migrations; 

public void Save(Person person) { 
    var db = new MyDbContext(); 
    db.People.AddOrUpdate(person); 
    db.SaveChanges(); 
} 
+5

Nie polecam używania AddOrUpdate podczas normalnego korzystania z bazy danych. Ta metoda jest przeznaczona tylko do zaszczepienia bazy danych, patrz [artykuł Julie Lerman] (http://thedatafarm.com/data-access/take-care-with-ef-4-3-addorupdate-method/) w celu uzyskania dalszych wyjaśnień. – Nick

+2

@Nick Artykuł ma dobry punkt. Jednakże, jeśli twórcy są świadomi, że AddOrUpdate nie może być użyty do aktualizacji tylko jednej właściwości bez uprzedniego posiadania kompletnego oryginalnego obiektu w celu zachowania pozostałych właściwości, to zastanawiam się, dlaczego nie? Jeśli masz tylko klucz podstawowy i chcesz ninja (tylko zmienić) jedną lub dwie właściwości, tak, wymagane jest inne kodowanie. Jeśli chodzi o moją odpowiedź dla Elad, dokumentacja metody mówi "Odpowiednik operacji" upsert "z terminologii bazy danych." – jaybro

+0

Wygląda na to, że podlega warunkom wyścigu, ponieważ robi to najpierw, aby ustalić, czy istnieje. –

Powiązane problemy