2017-07-24 15 views
6

Używam Entity Framework 6 i ObjectCache do buforowania niektórych jednostek, które nie zmieniają się często. Ale napotkałem błąd podczas próby zapisania encji, które są buforowane, ponieważ zostały pobrane z innego kontekstu. Przed zapisaniem, I zweryfikowane i stan obiektu został oderwany, ale nie mógł pozbyć się tego błędu, aż zrobiłem to:Entity Framework 6 i ObjectCache: zapisywanie problemów

public void Save(Product obj) 
{ 
    var objInDb = dbContext.Products.Find(obj.Id); 

    if (objInDb == null) 
    { 
     dbContext.Products.Add(obj); 
     dbContext.SaveChanges(); 
    } 
    else 
    { 
     dbContext.Entry(objInDb).CurrentValues.SetValues(obj); 
     dbContext.Entry(objInDb).State = EntityState.Modified; 
     dbContext.SaveChanges(); 
    } 
} 

Błąd Oryginalne, który został ustalony po wdrożył opisane rozwiązanie: Zakładanie podmiotem typ "C" nie powiódł się, ponieważ inna jednostka tego samego typu ma już tę samą wartość klucza podstawowego. Może się to zdarzyć w przypadku użycia metody "Dołącz" lub ustawienia stanu obiektu na "Niezmienione" lub "Zmodyfikowane", jeśli jakiekolwiek elementy na wykresie mają sprzeczne wartości klucza. Może to być spowodowane tym, że niektóre encje są nowe i nie otrzymały jeszcze wartości kluczy generowanych przez bazę danych. W takim przypadku użyj metody "Dodaj" lub "Dodany", aby śledzić wykres, a następnie odpowiednio ustaw stan nowych elementów na "Niezmienione" lub "Zmodyfikowane".

Oryginalny kod był:

if (obj.Id == 0) 
{ 
    context.Products.Add(obj); 
} 
else 
{ 
    context.Entry(obj).State = EntityState.Modified; 
} 

context.SaveChanges(); 

Czy istnieje lepszy sposób, aby sobie z tym poradzić? Naprawdę nie lubię ominąć mojej pamięci podręcznej i trafić do bazy danych, aby uzyskać obiekt, ponieważ wydaje mi się to niepotrzebne.

+0

Jaki był oryginalny kod, który wtedy nie działał? – DavidG

+0

Właśnie dodałem oryginalny kod do mojego pytania. –

+0

Czy masz włączoną opcję 'Configuration.ProxyCreationEnabled' w twoim kontekście? Domyślam się, że przechowujesz proxy w pamięci podręcznej, a nie rzeczywisty typ jednostki. – DavidG

Odpowiedz

0

Myślę, że jedynym sposobem na nie "uderzanie" de db byłoby coś takiego. Należy pamiętać, że na podstawie pierwszego wyjątku już "trafiasz" do bazy danych dla tego podmiotu gdzie indziej.

if (obj.Id == 0) 
{ 
    context.Products.Add(obj); 
} 
else 
{ 
    var localProduct = context.Products.Local.FirstOrDefault(x => x.Id == obj.Id); 
    if (localProduct == null) 
    { 
     context.Entry(obj).State = EntityState.Modified; 
    } 
    else 
    { 
     context.Entry(localProduct).CurrentValues.SetValues(obj); 
    } 
} 
context.SaveChanges(); 
Powiązane problemy