实体框架4 SaveChanges不工作,不会抛出任何错误?

时间:2011-09-18 11:02:52

标签: entity-framework entity-framework-4

我正在尝试将我的通用存储库与“工作单元”模式一起使用。

这是我的工作细节

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();
        }
    }
}

它让我检索实体,但是当我想创建一个实体时,它不会显示任何错误,也不会显示数据库中的任何更新。

任何线索都会有所帮助。

1 个答案:

答案 0 :(得分:3)

您的public static ObjectContext CurrentFor()方法将始终创建新的上下文。您的查询正在使用ObjectContext属性

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

因此,您使用的是ObjectContext的多个实例。您正在调用SaveChanges()的其他实例的ObjectContext。所以不会有任何变化。

不要像UnitOfWork中那样明确处理交易。 ObjectContext将完成该部分。

您的设计是一个复杂的抽象。尝试按原样使用框架,或者找到一个已经过测试的简单存储库模式。