实体框架4 SaveChanges不工作,不会抛出任何错误? [英] Entity Framework 4 SaveChanges not working and not throwing any error?
问题描述
这是我的工作细节
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添加< TEntity>(TEntity entity)其中TEntity:class
{
((DataEntities.MyTestDBEntities)_objectContext).Countries.AddObject Country(){CountryName =UGANDA});
this._objectContext.AddObject(GetEntityName< TEntity>(),entity);
}
public void Update< TEntity>(TEntity entity)其中TEntity:class
{
var fqen = GetEntityName< TEntity>();
对象originalItem;
EntityKey key = ObjectContext.CreateEntityKey(fqen,entity);
if(ObjectContext.TryGetObjectByKey(key,out originalItem))
{
ObjectContext.ApplyCurrentValues(key.EntitySetName,entity);
}
}
私有字符串GetEntityName< TEntity>()其中TEntity:class
{
return string.Format({0} 1},ObjectContext.DefaultContainerName,_pluralizer.Pluralize(typeof(TEntity).Name));
}
public object Get< TEntity>()其中TEntity:class
{
var entityName = GetEntityName< TEntity>();
return ObjectContext.CreateQuery< TEntity>(entityName);
}
public IEnumerable< TEntity>查找< TEntity>(表达式< Func< TEntity,bool>>标准)其中TEntity:class
{
返回GetQuery< TEntity>()
}
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>()其中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现有的交易仍在运行时,无法开始新的交易。+
在开始新的交易之前,请提交或回滚现有的交易。
}
OpenConnection();
_transaction = _objectContext.Connection.BeginTransaction(isolationLevel);
}
public void RollBackTransaction()
{
if(_transaction == null)
{
throw new ApplicationException(Can not roll在没有事务运行的情况下返回事务。);
}
try
{
_transaction.Rollback();
}
catch
{
throw;
}
finally
{
ReleaseCurrentTransaction();
}
}
public void CommitTransaction()
{
if(_transaction == null)
{
throw new ApplicationException(没有事务运行时不能回滚事务);
}
try
{
_objectContext.SaveChanges();
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
ReleaseCurrentTransaction();
public void SaveChanges()
{
if(IsInTransaction)
{
throw new ApplicationException(一个事务正在运行,调用BeginTransaction。);
}
_objectContext.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
}
public void SaveChanges(SaveOptions saveOptions)
{
if(IsInTransaction)
{
throw new ApplicationException(A transaction is运行,调用BeginTransaction。);
}
_objectContext.SaveChanges(saveOptions);
}
///< summary>
///发布当前事务
///< / summary>
private void ReleaseCurrentTransaction()
{
if(_transaction!= null)
{
_transaction.Dispose();
_transaction = null;
}
}
private void OpenConnection()
{
if(_objectContext.Connection.State!= ConnectionState.Open)
{
_objectContext.Connection.Open();
}
}
///< summary>
///执行与释放,释放或重置非托管资源相关联的应用程序定义任务。
///< / summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///< summary>
///配置托管和非托管资源。
///< / summary>
///< param name =disposal>< / param>
private void Dispose(bool disposal)
{
if(!disposal)
return;
if(_disposed)
return;
ReleaseCurrentTransaction();
_disposed = true;
}
private bool _disposed;
}
我通过我的 ContextManager
class:
public class ContextManager
{
///< summary> ;
///如果只传送一个数据库,则使用默认连接字符串名称。
///< / summary>
public static readonly string DefaultConnectionStringName =DefaultDb;
///< summary>
/// IObjectContextStorage的应用程序特定实现必须通过
///< see cref =InitStorage/>或者重载。
///< / summary>
private static IObjectContextStorage Storage {get;组; }
///< summary>
///维护对象上下文构建器的字典,每个数据库一个。关键是用于查找关联数据库的
///连接字符串名称,用于装饰相应的
///存储库。如果仅使用一个数据库,则该字典包含一个
///工厂,键值为< see cref =DefaultConnectionStringName/> ;.
///< / summary>
//私有静态字典< string,IObjectContextBuilder< ObjectContext>> objectContextBuilders = new Dictionary< string,IObjectContextBuilder< ObjectContext>>();
私有静态对象_syncLock = new object();
///< summary>
///如果您正在与单个数据库通信,则用于获取当前对象上下文会话。
///当与多个数据库通信时,调用< see cref =CurrentFor()/>代替。
///< / summary>
public static ObjectContext当前
{
get {return CurrentFor(); }
}
///< summary>
///用于获取与一个键相关联的当前ObjectContext;即与特定数据库的对象上下文相关联的键
///。
///
///如果您只与一个数据库进行通信,您应该调用< see cref =Current/>相反,
///虽然如果您有钥匙可用,您当然欢迎来电。
///< / summary>
public static ObjectContext CurrentFor()
{
ObjectContext context = null;
lock(_syncLock)
{
if(context == null)
{
context = new TestDAL.DataEntities.MyTestDBEntities();
//Storage.SetObjectContextForKey(key,context);
}
}
返回上下文;
}
///< summary>
///这个方法被应用程序特定的对象上下文存储实现
///和单元测试使用。它的工作是通过现有的缓存对象上下文和关闭()每一个。
///< / 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
中那样明确处理事务。
您的设计是一个复杂的抽象。尝试使用框架,或者找到一个已经被测试过的简单的Repository模式。
I am trying to use my generic repository with a "unit of work" pattern.
Here is my work details
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);
}
}
then I will redirect save changes and other committing the transaction with 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;
}
and I am getting my context through my ContextManager
class:
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();
}
}
}
it gives me retrieval of entities, but when I want to create an entity it doesn't shows nay error nor any update in the database.
Any clue will be helpful.
Your public static ObjectContext CurrentFor()
method will always create a new context. And your queries are using the ObjectContext
property
public ObjectContext ObjectContext
{
get { return ContextManager.CurrentFor(); }
}
Hence you are using multiple instances of ObjectContext
. You are calling SaveChanges()
of a different instance of ObjectContext
. So no changes will be persisted.
Do not handle the transactions explicitly as you did in UnitOfWork
. The ObjectContext
will do that part.
Your design is a complicated abstraction. Try to use the framework as it is or find a simple Repository pattern which has already being tested an used.
这篇关于实体框架4 SaveChanges不工作,不会抛出任何错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!