2013-06-26 6 views
0

Я использую Generic Repository/Единицу работы кода, используемую на образце Microsoft Contoso университета:EntityFramework SaveChanges перестает работать после ошибки

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

И он отлично работает (это экономит, извлекает, обновление, удаление и т. д.) до появления ошибки на уровне базы данных. В частности, я попытался создать вставку, в которой одно из полей было слишком коротким для текста, который был передан ему. Конечно, это провалилось. Ошибка задерживается в блоке try/catch, а затем отображается сообщение об ошибке. Проблема заключается в том, что после ввода новой информации в форму (это верно, как и при правильном размере текста) метод SaveChanges продолжает сбой с точно такой же ошибкой (поле XYZ должно быть строкой или типом массива с максимальной длиной «999»). Он только останавливается, пока я не остановить отладку и перезапустить выполнение проекта ASP.NET

Для ясности, это код, у меня есть: (GenericRepository.cs)

public class GenericRepository<TEntity> where TEntity : class 
{ 
    internal DBORAContext context; 
    internal DbSet<TEntity> dbSet; 

    public GenericRepository(DBORAContext context) 
    { 
     this.context = context; 
     this.dbSet = context.Set<TEntity>(); 
    } 

    public virtual IEnumerable<TEntity> Get(
     Expression<Func<TEntity, bool>> filter = null, 
     Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
     string includeProperties = "") 
    { 

     IQueryable<TEntity> query = dbSet; 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     foreach (var includeProperty in includeProperties.Split 
      (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
     { 
      query = query.Include(includeProperty); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 
    } 

    public virtual TEntity GetByID(object id) 
    { 
     return dbSet.Find(id); 
    } 

    public virtual void Insert(TEntity entity) 
    { 
     dbSet.Add(entity); 
    } 

    public virtual void Delete(object id) 
    { 
     TEntity entityToDelete = dbSet.Find(id); 
     Delete(entityToDelete); 
    } 

    public virtual void Delete(TEntity entityToDelete) 
    { 
     if (context.Entry(entityToDelete).State == EntityState.Detached) 
     { 
      dbSet.Attach(entityToDelete); 
     } 
     dbSet.Remove(entityToDelete); 
    } 

    public virtual void Update(TEntity entityToUpdate) 
    { 
     dbSet.Attach(entityToUpdate); 
     context.Entry(entityToUpdate).State = EntityState.Modified; 
    }     
} 

(UnitOfWork. CS)

public class UnitOfWork : IDisposable 
    { 
     private DBORAContext context = new DBORAContext();   
     private GenericRepository<Activity> activityRepository;   
     public GenericRepository<Activity> ActivityRepository 
     { 
      get 
      { 

       if (this.activityRepository == null) 
       { 
        this.activityRepository = new GenericRepository<Activity>(context); 
       } 
       return activityRepository; 
      } 
     }   

     public void Save() 
     {        
      context.SaveChanges(); 
     }     

     private bool disposed = false; 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!this.disposed) 
      { 
       if (disposing) 
       { 
        context.Dispose(); 
       } 
      } 
      this.disposed = true; 
     } 

     public void Dispose() 
     { 
      Dispose(true); 
      GC.SuppressFinalize(this); 
     } 
    } 

И это класс, который вызывает хранилище для данного конкретного объекта (Activity.cs)

public class Activity 
    { 
     private static readonly UnitOfWork unitOfWork = new UnitOfWork();     

     public static POCO.Activity Get(Guid activityId) 
     { 
      try 
      { 
       var thisActivity = unitOfWork.ActivityRepository.Get(a => a.ACTIVITYID == activityId).FirstOrDefault(); 

       if (null != thisActivity) 
       { 
        return thisActivity; 
       } 
       return null; 
      } 
      catch (Exception ex) 
      {     
       new Logger(ex.Message); 
       return null; 
      }    
     } 

     public static POCO.Activity Add(POCO.Activity activityToInsert) 
     { 
      try 
      { 
       unitOfWork.ActivityRepository.Insert(activityToInsert); 
       unitOfWork.Save(); 
       return activityToInsert; 
      }    
      catch (Exception ex) 
      { 
       //log.Error("Add activity error", ex); 
       new Logger(ex.Message); 
       throw; 
      } 
     } 

     public static bool Update(POCO.Activity activityToUpdate) 
     { 
      try 
      { 
       unitOfWork.ActivityRepository.Update(activityToUpdate); 
       unitOfWork.Save(); 
       return true; 
      }    
      catch (Exception ex) 
      { 
       //log.Error("update activity error", ex); 
       new Logger(ex.Message); 
       throw; 
      } 
     }  

     public static bool Delete(POCO.Activity activityToDelete) 
     { 
      try 
      { 
       unitOfWork.ActivityRepository.Delete(activityToDelete); 
       unitOfWork.Save(); 
       return true; 
      }    
      catch (Exception ex) 
      {     
       new Logger(ex.Message); 
       throw; 
      } 
     } 
    } 

Я использую EF 4.3 в базе данных Oracle. Пожалуйста помоги.

+0

Когда 'SaveChanges()' failed, контекст остается неизменным, поэтому все сущности, которые были добавлены в контекст, остаются «добавленными». Я действительно не понимаю, почему учебник, который вы используете, решил повторно использовать 'unitOfWork'. У вас не было бы этой проблемы, если бы вы создали новый контекст (новый 'UnitOfWork') для каждого действия, которое вы пытаетесь сохранить. – hvd

+0

Что-то вроде того, чего я боялся. Как вы предлагаете мне изменить свой код? – webyacusa

+0

Я * хотел бы просто подумать, используя (var unitOfWork = new UnitOfWork()) {...} 'в' Add' и т. Д., И удалять 'private static readonly UnitOfWork unitOfWork', но это оставляет ваши POCOs привязанными к теперь -разложенный контекст, и это также вызывает проблемы. Он должен работать, если вы обязательно отключите свои POCO после сохранения (даже в случае исключения). – hvd

ответ

0

проблема заключается в том, что ваша единица работы является одноэлементной. единица работы нуждается в меньшем объеме. если это веб-приложение, то http-контекст является хорошим объектом для охвата UoW.

request.begin -> начать UOW request.end -> полного UOW

Если это услуга, то каждый запрос к услуге можно начать/закончить UOW.

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

+0

Это веб-приложение (веб-формы ASP.NET, а не MVC). Можете ли вы дать мне более конкретный пример того, как реализовать этот рабочий процесс? – webyacusa

+0

Есть много примеров онлайн. найдите «контекст сущности для каждого запроса». большинство примеров, вероятно, будут использовать MVC, но то же самое можно сделать для Webforms. это специфично для asp.net, а не для mvc или webforms. –