我正在使用存儲庫和工作單元模式和依賴項注入來訪問我的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注入UserUnitOfwork
。 IUserUserOfWork
包含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方法的數據庫正確更新。但是,行爲仍然不正確。當我註銷並首先檢索正確的值。當我再次更改並註銷時,它不會更新。這是之前的模式,它在我註銷和註銷後得到第一個更新,但是如果我再次更改並註銷,並且它沒有提取它。
聽起來好像您的上下文不會被創建/銷燬每個請求。你的上下文如何被注入實例化?使用Unity的 –
像這樣:container.RegisterType(); –
Neil
放棄所有這些「UnitOfWork」和「Repository」並使用裸EF工作。它將爲您節省大量頭痛,並且您的代碼最終會變得非常簡單。 – Euphoric