2011-09-18 79 views
2

我想用「工作單元」模式來使用我的通用存儲庫。實體框架4 SaveChanges不工作,並沒有拋出任何錯誤?

這裏是我的工作細節

public class GenericRepository:IRepository 
{ 

    private readonly string _connectionStringName; 
    private ObjectContext _objectContext; 
    private readonly PluralizationService _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en")); 

    public GenericRepository() 
    { 
     this._objectContext = ContextManager.CurrentFor(); 
    } 

    public void Add<TEntity>(TEntity entity) where TEntity : class 
    { 
     ((DataEntities.MyTestDBEntities)_objectContext).Countries.AddObject(new Country() { CountryName="UGANDA"}); 
     this._objectContext.AddObject(GetEntityName<TEntity>(), entity); 
    } 

    public void Update<TEntity>(TEntity entity) where TEntity : class 
    { 
     var fqen = GetEntityName<TEntity>(); 

     object originalItem; 
     EntityKey key = ObjectContext.CreateEntityKey(fqen, entity); 
     if (ObjectContext.TryGetObjectByKey(key, out originalItem)) 
     { 
      ObjectContext.ApplyCurrentValues(key.EntitySetName, entity); 
     } 
    } 

    private string GetEntityName<TEntity>() where TEntity : class 
    { 
     return string.Format("{0}.{1}", ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name)); 
    } 

    public object Get<TEntity>() where TEntity : class 
    { 
     var entityName = GetEntityName<TEntity>(); 
     return ObjectContext.CreateQuery<TEntity>(entityName); 
    } 

    public IEnumerable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class 
    { 
     return GetQuery<TEntity>().Where(criteria); 
    } 

    private IUnitOfWork unitOfWork; 

    public ObjectContext ObjectContext 
    { 
     get { return ContextManager.CurrentFor(); } 
    } 

    public IUnitOfWork UnitOfWork 
    { 
     get 
     { 
      if (unitOfWork == null) 
      { 
       unitOfWork = new UnitOfWork(this.ObjectContext); 
      } 
      return unitOfWork; 
     } 
    } 

    public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class 
    { 
     var entityName = GetEntityName<TEntity>(); 
     return ObjectContext.CreateQuery<TEntity>(entityName); 
    } 
} 

然後我將重定向保存UnitOfWork.cs

public class UnitOfWork:IUnitOfWork 
{ 
    private DbTransaction _transaction; 
    private ObjectContext _objectContext; 

    public UnitOfWork(ObjectContext context) 
    { 
     _objectContext = context; 
    } 

    public bool IsInTransaction 
    { 
     get { return _transaction != null; } 
    } 

    public void BeginTransaction() 
    { 
     BeginTransaction(IsolationLevel.ReadCommitted); 
    } 

    public void BeginTransaction(IsolationLevel isolationLevel) 
    { 
     if (_transaction != null) 
     { 
      throw new ApplicationException("Cannot begin a new transaction while an existing transaction is still running. " + 
              "Please commit or rollback the existing transaction before starting a new one."); 
     } 
     OpenConnection(); 
     _transaction = _objectContext.Connection.BeginTransaction(isolationLevel); 
    } 

    public void RollBackTransaction() 
    { 
     if (_transaction == null) 
     { 
      throw new ApplicationException("Cannot roll back a transaction while there is no transaction running."); 
     } 

     try 
     { 
      _transaction.Rollback(); 
     } 
     catch 
     { 
      throw; 
     } 
     finally 
     { 
      ReleaseCurrentTransaction(); 
     } 
    } 

    public void CommitTransaction() 
    { 
     if (_transaction == null) 
     { 
      throw new ApplicationException("Cannot roll back a transaction while there is no transaction running."); 
     } 

     try 
     { 
      _objectContext.SaveChanges(); 
      _transaction.Commit(); 
     } 
     catch 
     { 
      _transaction.Rollback(); 
      throw; 
     } 
     finally 
     { 
      ReleaseCurrentTransaction(); 
     } 
    } 

    public void SaveChanges() 
    { 
     if (IsInTransaction) 
     { 
      throw new ApplicationException("A transaction is running. Call BeginTransaction instead."); 
     } 
     _objectContext.SaveChanges(SaveOptions.AcceptAllChangesAfterSave); 
    } 

    public void SaveChanges(SaveOptions saveOptions) 
    { 
     if (IsInTransaction) 
     { 
      throw new ApplicationException("A transaction is running. Call BeginTransaction instead."); 
     } 
     _objectContext.SaveChanges(saveOptions); 
    } 

    /// <summary> 
    /// Releases the current transaction 
    /// </summary> 
    private void ReleaseCurrentTransaction() 
    { 
     if (_transaction != null) 
     { 
      _transaction.Dispose(); 
      _transaction = null; 
     } 
    } 

    private void OpenConnection() 
    { 
     if (_objectContext.Connection.State != ConnectionState.Open) 
     { 
      _objectContext.Connection.Open(); 
     } 
    } 

    /// <summary> 
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 
    /// </summary> 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    /// <summary> 
    /// Disposes the managed and unmanaged resources. 
    /// </summary> 
    /// <param name="disposing"></param> 
    private void Dispose(bool disposing) 
    { 
     if (!disposing) 
      return; 

     if (_disposed) 
      return; 

     ReleaseCurrentTransaction(); 

     _disposed = true; 
    } 
    private bool _disposed; 
} 

變化等提交事務,我通過我的ContextManager類讓我的背景:

public class ContextManager 
{ 
    /// <summary> 
    /// The default connection string name used if only one database is being communicated with. 
    /// </summary> 
    public static readonly string DefaultConnectionStringName = "DefaultDb"; 

    /// <summary> 
    /// An application-specific implementation of IObjectContextStorage must be setup either thru 
    /// <see cref="InitStorage" /> or one of the <see cref="Init" /> overloads. 
    /// </summary> 
    private static IObjectContextStorage Storage { get; set; } 

    /// <summary> 
    /// Maintains a dictionary of object context builders, one per database. The key is a 
    /// connection string name used to look up the associated database, and used to decorate respective 
    /// repositories. If only one database is being used, this dictionary contains a single 
    /// factory with a key of <see cref="DefaultConnectionStringName" />. 
    /// </summary> 
    // private static Dictionary<string, IObjectContextBuilder<ObjectContext>> objectContextBuilders = new Dictionary<string, IObjectContextBuilder<ObjectContext>>(); 

    private static object _syncLock = new object(); 

    /// <summary> 
    /// Used to get the current object context session if you're communicating with a single database. 
    /// When communicating with multiple databases, invoke <see cref="CurrentFor()" /> instead. 
    /// </summary> 
    public static ObjectContext Current 
    { 
     get { return CurrentFor(); } 
    } 

    /// <summary> 
    /// Used to get the current ObjectContext associated with a key; i.e., the key 
    /// associated with an object context for a specific database. 
    /// 
    /// If you're only communicating with one database, you should call <see cref="Current" /> instead, 
    /// although you're certainly welcome to call this if you have the key available. 
    /// </summary> 
    public static ObjectContext CurrentFor() 
    { 
     ObjectContext context = null; 
     lock (_syncLock) 
     {    
      if (context == null) 
      { 
       context =new TestDAL.DataEntities.MyTestDBEntities(); 
       //Storage.SetObjectContextForKey(key, context); 
      } 
     } 

     return context; 
    } 

    /// <summary> 
    /// This method is used by application-specific object context storage implementations 
    /// and unit tests. Its job is to walk thru existing cached object context(s) and Close() each one. 
    /// </summary> 
    public static void CloseAllObjectContexts() 
    { 
     if (CurrentFor().Connection.State == System.Data.ConnectionState.Open) 
     { 
      CurrentFor().Connection.Close(); 
     } 
    } 
} 

它給我檢索實體,但是當我想創建一個它不會顯示錯誤的實體,也不會在數據庫中進行任何更新。

任何線索都會有所幫助。

回答

3

您的public static ObjectContext CurrentFor()方法將始終創建一個新的上下文。和你的查詢使用ObjectContext財產

public ObjectContext ObjectContext 
{ 
    get { return ContextManager.CurrentFor(); } 
} 

因此,你所使用的ObjectContext多個實例。您正在致電ObjectContext的其他實例的SaveChanges()。所以沒有改變會持續下去。

不要像在UnitOfWork中那樣明確處理交易。 ObjectContext將做那部分。

您的設計是一個複雜的抽象。嘗試按原樣使用框架,或者找到一個已經被測試過的簡單Repository模式。

相關問題