entity-framework - Entity Framework 4 SaveChanges 不起作用并且没有抛出任何错误?

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

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

任何线索都会有帮助。

最佳答案

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

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

因此,您正在使用 ObjectContext 的多个实例。您正在调用 ObjectContext 的不同实例的 SaveChanges()。因此不会保留任何更改。

不要像在 UnitOfWork 中那样显式处理事务。 ObjectContext 将完成该部分。

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

关于entity-framework - Entity Framework 4 SaveChanges 不起作用并且没有抛出任何错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7461039/

相关文章:

c# - ADO.NET Entity Framework : How to get auto cascading deletions?

c# - SQL 差异 EF 6 与 EF Core

c# - DTO 加上 UnitOfWork 模式是为 Web 应用程序设计 DAL 的好方法吗?

c# - Entity Framework 错误(分部方法可能没有多个定义声明)

.net - 如何使用 EF CTP5 Fluent API 在一对多关系中关闭级联删除

c# - 如何使用poco实体生成器

sql - 如何让 INotifyPropertyChanged 从存储在 SQL 中的列表中更新绑定(bind)项目?

c# - 部分查看文件上传

entity-framework - 如何将一个代码第一个对象中的两个属性映射到相同的父类型

linq - 有没有办法使用 LINQ/EF 来获取父/子层次结构中最顶层的项目?