2013-06-26 54 views
0

我使用微軟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; 
      } 
     } 
    } 

我在Oracle數據庫上使用EF 4.3。請幫忙。

+0

當SaveChanges()失敗時,上下文保持不變,因此添加到上下文的所有實體都保留爲「已添加」。我真的不明白爲什麼你使用的教程決定重用'unitOfWork'。如果您爲嘗試保存的每個操作創建了新的上下文(一個新的「UnitOfWork」),則不會出現此問題。 – hvd

+0

這樣的事情就是我所害怕的。你如何建議我應該改變我的代碼? – webyacusa

+0

我會*認爲只是在'Add'等中使用(var unitOfWork = new UnitOfWork()){...}',並刪除'private static readonly UnitOfWork unitOfWork',但這會使您的POCO連接到一個now偏離的背景下,這也會導致問題。如果你確保在保存後明確地分離你的POCO(即使在例外的情況下),它應該可以工作。 – hvd

回答

0

問題是你的工作單元是單身人士。工作單位需要較小的範圍。如果這是一個Web應用程序,http上下文對於範圍UoW是一個很好的對象。

request.begin - >啓動UOW request.end - >完整的UOW

如果這是一個服務,則每個請求到服務可以開始/結束UOW。

如果這是一個富客戶端,那麼您可以將其範圍擴展到每個UI表單。

+0

這是一個web應用程序(ASP.NET webforms,而不是MVC)。你能給我一個關於如何實現這個工作流的更具體的例子嗎? – webyacusa

+0

網上有很多例子。搜索「每個請求的實體框架上下文」。大多數例子可能會使用MVC,但Webforms也可以做到這一點。這是特定於asp.net,而不是mvc或webforms。 –