2017-02-17 12 views
1

У меня есть веб-сайт, который использует ASP.NET MVC 5 с EF6.1, и у меня возникла проблема с его отображением старых данных после процедуры редактирования. Данные сохраняются в базе данных должным образом, но при перенаправлении на просмотр индекса все еще отображаются старые данные.Задание обновления DBContext после создания/редактирования ASP.NET MVC EF 6.1

Если я вернусь к представлению «Редактировать», он по-прежнему покажет старые данные. DBContext, похоже, не обновляет данные.

У меня есть базовый контроллер, который содержит DBC-текст, если это имеет значение.

Вот код для просмотра Редактировать в мой контроллер:

public ActionResult FeaturedItemEdit(int? id) 
    { 
     if (id == null) 
     { 
      return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 
     using (nfmContext localContext = new nfmContext()) 
     { 
      List<FeaturedItem> fi = localContext.FeaturedItems.AsNoTracking().ToList(); 

      FeaturedItem featuredItem = fi.Find(x => x.ID.Equals(id)); 

      if (featuredItem == null) 
      { 
       return HttpNotFound(); 
      } 
      return View(featuredItem); 
     } 
    } 

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult FeaturedItemEditPost(int? id) 
    { 
     if (id == null) 
     { 
      return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 
     using (nfmContext db = new nfmContext()) 
     { 
      var item = db.FeaturedItems.Find(id); 
      if (TryUpdateModel(item, "", new string[] { "ID", "Title", "ImageAlt", "ImagePath", "Link", "Visible", "Content" })) 
      { 
       try 
       { 
        item.TimeStamp = DateTime.Now; 
        db.Entry(item).State = EntityState.Modified; 
        db.SaveChanges(); 

        return RedirectToAction("FeaturedItems"); 
       } 
       catch (DataException ex) 
       { 
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 
       } 
      } 
      return View(item); 
     } 
    } 

После редактирования будет сделано, он возвращается к Показанные Пункты просмотра, который просто загружает список элементов:

public ActionResult FeaturedItems() 
    { 
     using (nfmContext localContext = new nfmContext()) 
     { 
      return View(localContext.FeaturedItems.OrderBy(x => x.Visible).ThenBy(x => x.Title).AsNoTracking().ToList()); 
     } 
    } 

Ничего особенного. Сначала я подумал, что это вызвано тем, что все звонки были async, но, изменив его обратно на неасинхронный, это не имело большого значения. Я не размещал код для создания элемента, однако у него такая же проблема.

Я даже украсил свой контроллер [OutputCache(Location = System.Web.UI.OutputCacheLocation.None)], чтобы убедиться, что это не проблема кеширования на стороне клиента.

Итак, я делаю что-то неправильно или есть способ заставить DBContext извлекать свежие записи из базы данных?

UPDATE 1: Вот линия, которая инициализирует мой DbContext в базовом контроллере:

 <strike>protected nfmContext db = new nfmContext();</strike> 

Это больше не используется - см обновления 2

А вот мои настройки контекста:

public class nfmContext : DbContext 
{ 
    public nfmContext() : base("connectionStringHere") 
    { 
    } 

    public DbSet<FeaturedItem> FeaturedItems { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
     modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 

     base.OnModelCreating(modelBuilder); 

    } 
} 

ОБНОВЛЕНИЕ 2: Я переключил DBC ontect теперь будет локальным для каждого метода. В приведенном выше коде отражены изменения, и я удалил свойство DBContect с базового контроллера.

+0

Это работает, если вы поместили эту строку 'db = new YourContextName()' после изменения? –

+0

Да, это потому, что вы не закрываете свой контекст. См. [Здесь] (http://stackoverflow.com/questions/14449308/entity-framework-returning-old-data). Я рекомендую использовать контейнер IoC, например [Autofac] (http://stackoverflow.com/questions/29560294/ впрыснуть-DbContext-с-autofac). –

+0

Вы должны добавить код, который инициализирует dbcontext, поскольку он играет важную роль в этом вопросе, и я думаю, что проблема будет там. – BennyM

ответ

0

Обнаружил проблему после проскакивания и поиска в проекте для различных реализаций кэширования.

В какой-то момент в проекте была установлена ​​EntityFramework.Cache (или EFCache, как указано). Это вызвало проблему кэширования, хотя она была создана на основе их документации.

SaveChanges предполагается совершить в транзакции (как я полагаю, это так), и EFCache должен следить за транзакциями и обновлять кеш. Где-то с двумя есть разрыв, где кеш не истекает.

Для справки, вот что я использую для реализации вторичного кэширования для рамок:

public class Configuration : DbConfiguration 
{ 
    public Configuration() 
    { 
     var transactionHandler = new CacheTransactionHandler(new InMemoryCache()); 
     AddInterceptor(transactionHandler); 

     var cachingPolicy = new CachingPolicy(); 

     Loaded += 
      (sender, args) => args.ReplaceService<DbProviderServices>(
       (s, _) => new CachingProviderServices(s, transactionHandler, 
       cachingPolicy)); 
    } 


} 

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

Для того, чтобы заставить его работать и дать мне возможность очистить DbSet по запросу, я включил объявление CacheTransactionHandler, чтобы использовать статические InMemoryCache. Затем, как только он был установлен таким образом, я мог бы использовать InvalidateDbSets, чтобы удалить элемент из кэша памяти.

Вот что я сделал именно:

  • Добавлено это мой DbContext:

public static readonly EFCache.InMemoryCache Cache = new EFCache.InMemoryCache();

  • Изменена transactionHandler декларации в подменю конфигурации для:

var transactionHandler = new CacheTransactionHandler(nfmContext.Cache);

  • После любых .SaveChanges звонков, я добавил:

nfmContext.Cache.InvalidateSets(new List<string>() { "[insert entity name here]" });

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

0

Всегда используйте свой dbContext столько, сколько потребуется. Обычно используйте метод using внутри метода. Повторное открытие соединения с базой данных не займет много времени из-за пула соединений.

+1

Я создал локальный DBContext в каждом методе и завернул это с 'использованием', но это ничего не изменило, к сожалению. – hacker