2014-03-24 77 views
1

我正在使用存儲庫和工作單元模式和依賴項注入來訪問我的Web應用程序中實體框架5的數據庫。我有一個User類,實體框架生成Code-First數據庫。實體框架在使用存儲庫模式時不刷新數據

public class User 
{ 
    public Guid UserId { get; set; } 
    public string UserName { get; set; } 
       . 
       . 
       . 
    public string LanguagePreference { get; set; } 
    public virtual List<Role> Roles { get; set; } 
    public virtual List<Branch> Branches { get; set; } 

} 

我有一個UserService類用於添加或更新用戶。該類在構造函數中使用IUserUnitOfWork作爲參數,Unity注入UserUnitOfworkIUserUserOfWork包含IRepository<User>IRepository<Location>IRepository<Role>。 DI引導程序將它們設置爲Repository<T>。 IUserUnitOfWork使用相同的實體框架DbContext設置不同的存儲庫。我這樣做是因爲我在更新與用戶(位置和角色)相關的多對多關係時遇到問題。

UserUnitOfWork:

public IRepository<Branch> BranchRepository {get; set;} 
    public IRepository<Role> RoleRepository { get; set; } 
    public IRepository<User> UserRepository { get; set; } 
    public DbContext Context { get; set; } 

    public UserUnitOfWork(DbContext context, ITransientErrorDetectionStrategy errorDetectionStrategy,RetryStrategy retryStrategy) 
    { 
     Context = context; 
     BranchRepository = new Repository<Branch>(context, errorDetectionStrategy, retryStrategy); 
     RoleRepository = new Repository<Role>(context, errorDetectionStrategy, retryStrategy); 
     UserRepository = new Repository<User>(context, errorDetectionStrategy, retryStrategy); 
    } 

資源庫類,然後使用實體框架5訪問數據庫。從Repository.FirstOrDefault方法

例子:

public virtual T FirstOrDefault(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "") 
    { 
     T result = null; 

     _retryPolicy.ExecuteAction(() => 
     { 
      IQueryable<T> entities = GetHelper(filter, orderBy, includeProperties); 

      result = entities.FirstOrDefault(); 
     }); 


     return result; 
    } 

和更新來自庫:

public virtual void Update(T entity) 
    { 
     if (_dbContext.Entry(entity).State == System.Data.EntityState.Detached) 
     { 
      _dbContext.Set<T>().Attach(entity); 
      _dbContext.Entry(entity).State = System.Data.EntityState.Modified; 
     } 
    } 

所以我現在的問題是,當我更新的用戶它正確在數據庫中更新數據,並且當我註銷並登錄最初的更改工作時。但是,如果我再次更新並註銷,並且即使更新了數據庫,也無法獲取新更改。

我開始擔心,我採取的方法不正確,可有人告訴我如何確保,當我做一個更新實體框架總是會得到最新版本?

編輯:

所以我創建每個請求的生命週期管理器,像這樣:

public class PerHttpRequestLifetimeManager : LifetimeManager 
{ 
    private readonly object key = new object(); 

    public override object GetValue() 
    { 
     if (HttpContext.Current != null && 
      HttpContext.Current.Items.Contains(key)) 
      return HttpContext.Current.Items[key]; 
     else 
      return null; 
    } 

    public override void RemoveValue() 
    { 
     if (HttpContext.Current != null) 
      HttpContext.Current.Items.Remove(key); 
    } 

    public override void SetValue(object newValue) 
    { 
     if (HttpContext.Current != null) 
      HttpContext.Current.Items[key] = newValue; 
    } 
} 

在我的引導程序DI現在我安裝我的域上下文象下面這樣:

 container.RegisterType<DbContext, DomainContext>(new PerHttpRequestLifetimeManager()); 

它似乎仍然沒有工作,我是否錯過了其他的東西,還是我錯誤地設置了它?

編輯2:

只是想指出的架構:

我們有一個使用角JS做出一個Web API服務層的Ajax調用MVC應用程序。 Web Api中注入了一個ISomethingService。正是這個ISomethingService將注入其中的存儲庫。對於PerHttpRequestLifetimeManager會有一些混淆,因爲有一個MVC和Web API項目正在運行?

編輯3:

我如何保存編輯用戶的例子:

我們有一個用於ServiceLayer之間的通信UserModel類 - > API - > UI層和背部。 User類是由Entity Framework代碼首先生成的類。 UserService中的EditUser方法需要UserModel

我那麼用戶_unitOfWork.UserRepository得到相應的數據庫用戶

var editedUser = _unitOfWork.UserRepository.FirstOrDefault(x => x.UserId == userModel.UserId); 

我的領域從的usermodel到editedUser地圖,然後我打電話(在UserService)

_unitOfWork.UserRepository.Update(editedUser) 

之後

_unitOfWork.Save() 

繼續編輯:

所以我編輯了一個簡單的方法,更新用戶表(語言首選項)上的單個文本字段。我在更新後顯式調用dispose方法,以確保我正在處理該方法。

public void SetUserLanguagePreference(Guid userId, string language) 
    { 
     var user = _unitOfWork.UserRepository.FirstOrDefault(x => x.UserId == userId); 

     user.LanguagePreference = language; 

     _unitOfWork.UserRepository.Update(user); 
     _unitOfWork.Save(); 
     _unitOfWork.Dispose(); 
    } 

UnitOfWork.Dispose()調用庫和的DbContext

的Dispose方法的數據庫正確更新。但是,行爲仍然不正確。當我註銷並首先檢索正確的值。當我再次更改並註銷時,它不會更新。這是之前的模式,它在我註銷和註銷後得到第一個更新,但是如果我再次更改並註銷,並且它沒有提取它。

+2

聽起來好像您的上下文不會被創建/銷燬每個請求。你的上下文如何被注入實例化?使用Unity的 –

+0

像這樣:container.RegisterType (); – Neil

+2

放棄所有這些「UnitOfWork」和「Repository」並使用裸EF工作。它將爲您節省大量頭痛,並且您的代碼最終會變得非常簡單。 – Euphoric

回答

4

最後,不是編輯而是答案!我們使用基於聲明的身份驗證,並擁有一個覆蓋ClaimsPrinciple Authenticate方法的類,每當用戶通過身份驗證時都會調用該方法。

public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
    { 
     if (incomingPrincipal.Identity.IsAuthenticated) 
     { 
      //Check here if the authenticated user has access to this system 
      //using the user repository and if so add more claims to the token 
     } 
     return base.Authenticate(resourceName, incomingPrincipal); 
    } 

這是不可能注入使用DI,因爲它總是跑到空的構造這個方法(不知道爲什麼,但是這事情是這樣的)。

所以不是我們在空的構造像這樣設置庫:

public PRAuthenticationManager() 
    { 
     _userRepository = DiBootstrapper.Container.Resolve<IRepository<User>>(); 
    } 

當身份驗證方法被調用時,我們檢查我們的數據庫與連接到ClaimsPrincipal權利要求的用戶。如果我們進行匹配,我們會向令牌添加新的聲明,這些聲明隨後將用於每次對Web Api的調用。這個存儲庫沒有被丟棄(即使其他所有的存儲庫都是這樣),所以當用戶註銷並且他們從相同的上下文中獲得了數據時,這些數據還沒有從最後一次用戶登錄時丟棄。

三滿幾天試圖找到一個....