I have taken over the coding of a software and the way it is currently done, I am not sure that the Dispose() method in the UnitOfWorks is getting called. I have noticed that my SQL service tends to stop after a while (days) saying that all connections are being used up.
I would like to know if the below code is properly done and if not, how I can go about rectifying so that it calls the dispose() method.
UnitOfWorks.cs
public class UnitOfWorks
{
private KaprukaEntities context;
private GenericRepository<Transaction> transactionRepository;
private bool disposed;
public GenericRepository<Transaction> TransactionRepository
{
get
{
if (this.transactionRepository == null)
this.transactionRepository = new GenericRepository<Transaction>(this.context);
return this.transactionRepository;
}
}
public UnitOfWorks(KaprukaEntities entities)
{
this.context = entities;
}
public void Save()
{
this.context.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed && disposing)
this.context.Dispose();
this.disposed = true;
}
public interface IDisposable
{
void Dispose();
}
}
The UnitOfWorks is getting called by a service class.
TransactionService.cs
public class TransactionService
{
private UnitOfWorks _unitOfWork;
private KaprukaEntities entities;
public TransactionService(UnitOfWorks unitOfWork)
{
this._unitOfWork = unitOfWork;
this.entities = new KaprukaEntities();
}
public bool Add(Transaction entity)
{
this._unitOfWork.TransactionRepository.Add(entity);
this._unitOfWork.Save();
var er = this.entities.GetValidationErrors();
return true;
}
public bool Update(Transaction entity)
{
this._unitOfWork.TransactionRepository.Update(entity);
this._unitOfWork.Save();
return true;
}
public bool Delete(Transaction entity)
{
this._unitOfWork.TransactionRepository.Delete(entity);
this._unitOfWork.Save();
return true;
}
public IEnumerable<Transaction> GetAll()
{
return this._unitOfWork.TransactionRepository.GetAll();
}
public IEnumerable<Transaction> GetAll(Expression<Func<Transaction, bool>> filter, Func<IQueryable<Transaction>, IOrderedQueryable<Transaction>> orderBy, string includeProperties)
{
return this._unitOfWork.TransactionRepository.Get(filter, orderBy, includeProperties);
}
}
The way this is getting called is as follows:
There is a file named updateTransaction.aspx and in its code behind, the code calls the service as such:
updateTransaction.aspx
TransactionService TransServ = new TransactionService(new UnitOfWorks(new KaprukaEntities()));
var TransDetails = TransServ.GetAll(x => x.TransactionID == intTID, null, "").SingleOrDefault();
I can't see any code to close or dispose anything.
Your transactionservice constructor creates an extra db context, when one is already in the unit of work class:
this.entities = new KaprukaEntities();
Related
I have project that is running just fine. However I am getting a CA1063 error and before I suppress I want to see if I am implement Dispose incorrectly.
It starts with an interface I have defined:
public interface IAttributeRepository
{
IDataTransaction BeginTransaction();
Task<IQueryable<AttributeValue>> GetAttributeValues(int parentId);
...etc....
}
Notice that anything implementing this interface must also implement IDataTransaction so here that is:
public interface IDataTransaction : IDisposable
{
void Commit();
void RollBack();
}
Now I have defined two types of SQL interactions in my repository layer. Simple one and then those that should be wrapped in a transaction.
The transaction one is what we care about and it is defined as a private class member var as such:
private DBTransaction _dbTransaction;
The class DBTransaction looks like this:
(DbTransaction is a Msoft object in System.Data.Entity)
public class DBTransaction : IDataTransaction
{
DbContextTransaction _dbcontextTrans;
public DBTransaction(DbContextTransaction dbcontexttrans)
{ _dbcontextTrans = dbcontexttrans; }
public void Commit()
{ _dbcontextTrans.Commit(); }
public void RollBack()
{ _dbcontextTrans.Rollback(); }
public void Dispose()
{ _dbcontextTrans.Dispose(); }
}
Finally in a repository class it would be used like this:
public class AttributeRepository : IAttributeRepository
{
public IDataTransaction BeginTransaction()
{
var trans = _DataContext.Database.BeginTransaction(IsolationLevel.ReadCommitted);
_dbTransaction = new DBTransaction(trans);
return _dbTransaction;
}
public async Task<IQueryable<Data.Attribute>> GetAttribute_with_AttributeValues(int id)
{
using (var trans = this.BeginTransaction())
{
//execute sql code you want wrapped in a transaction
//rollback, commit etc based upon result
trans.Commit();
}
}
}
As I mentioned the code executes correctly I'm just not sure I understand why code analysis is telling me my dispose needs correcting and before I just suppress it I want to verify with those far more knowledgeable than I.
TIA
Useful info here: Framework Design Guidelines - Dispose Pattern
This is the pattern I would follow when implementing IDisposable on the DBTransaction class:
public class DBTransaction : IDataTransaction
{
....
~DBTransaction() {
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if(_disposed) return;
try
{
// DISPOSE OF UN-MANAGED RESOURCES HERE
if(disposing)
{
// Dispose objects here
_dbcontextTrans.Dispose();
}
}
finally
{
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
...
}
If you are deriving from a base class that implements IDisposable and has a virtual dispose method, then I would do this:
protected override void Dispose(bool disposing)
{
if(_disposed)
return;
try
{
// DISPOSE OF UN-MANAGED RESOURCES HERE
if(disposing)
{
// Dispose objects here
}
}
finally
{
_disposed = true;
base.Dispose(disposing);
}
}
This is very similar to the normal Dispose(bool disposing), but in the finally block I call base.Dispose(disposing).
EDIT #1:
Updated to take into account suggestion from #juharr.
I have a WPF Project which is n-tier architecture and I use context per/call as it has Direct-database and web-service
Sorry a bit long question
Presentation => Business Layer => Data Layer
In datalayer i have UnitOfWork pattern implemented.
Initally when my DefaultAccessPoint was a Static property i had issues on multiple thread using the same context.
I had resolved it by changing the DefaultAccessPoint to a non-static property, and seems that multi thread issue had been Resolved .
after the fix =>(e.g) User could insert data into the Application on First tab(which takes approx. 3 mins) and simultaneously access the Second Tab(To fetch some data) while both are done in separate threads.
But after this Fix the Context doesn't refresh when a modification is done
The initial fix was done under DataProviderBase class were i changed static DataAccessPoint to Non-static and commented those lines that you see below.
How would i keep the context refresh with multi threading ?
Any Help is appreciated
Code Block
This is my dataproviderbaseclass every data-provider is inherited this base
public abstract class DataProviderBase
{
public DataProviderBase()
{
DefaultAccessPoint = new DataAccessAccessPoint(ConnectionString);
}
protected readonly ILogger logger = LoggerFactory.GetLogger();
private static string _connectionString;
public static string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
//COMMENTED as Fix for multiThreading
//_defaultAccessPoint = new DataAccessAccessPoint(ConnectionString);
}
}
private IDataAccessAccessPoint _defaultAccessPoint;
public IDataAccessAccessPoint DefaultAccessPoint
{
get
{
//COMMENTED as Fix for multi Threading
// Removed statis Default AccessPoint that was causing the issue
return _defaultAccessPoint; //?? (_defaultAccessPoint = new DataAccessAccessPoint(ConnectionString));
}
set { _defaultAccessPoint = value; }
}
}
This is my DataAccessPoint
public class DataAccessAccessPoint : IDataAccessAccessPoint
{
private string _connectionString;
public string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
}
}
private IDataContext context;
public DataAccessAccessPoint(string connectionString)
{
_connectionString = connectionString;
context = new MyDataContext(_connectionString);
}
public virtual bool Save()
{
return context.SaveChanges() > 0;
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//Here i supply the context to my Data access layers
private IMyDataLayerDA _myDA;
public IMyDataLayerdDA MydDA
{
get { return _myDA ?? (_myDA = new MydDA(context)); }
set { _myDA = value; }
}
}
My DataProvider
public class PersonRoleDataProvider : DataProviderBase, IPersonRoleDataProvider
{
public MYDTOCLASS AuthenticateUser(string userId)
{
return DefaultAccessPoint.MydDA.AuthenticateUser(userId);
}
public IEnumerable<MYDTOCLASS> GetRoles(int personId)
{
return DefaultAccessPoint.MydDA.GetRoles(personId);
}
}
DataProviderAccessPoint
public class DataProviderAccessPoint
{
private static PersonRoleDataProvider _personRoleDataProvider;
public static PersonRoleDataProvider PersonRoleDataProvider
{
get
{
if(_personRoleDataProvider==null)
_personRoleDataProvider = new PersonRoleDataProvider();
return _personRoleDataProvider;
}
}
}
public interface IRepository<T> : IDisposable
{
void Add(T newEntity);
void Delete(T entity);
T Find(int id);
IQueryable<T> FindAll();
int Commit();
}
public class SqlRepository<T> : IRepository<T> where T : class
{
DbContext context;
DbSet<T> set;
public SqlRepository(DbContext context)
{
this.context = context;
this.set = context.Set<T>();
}
public void Add(T newEntity)
{
this.set.Add(newEntity);
}
public void Delete(T entity)
{
}
public T Find(int id)
{
throw new Exception("todo");
}
public IQueryable<T> FindAll()
{
return this.set;
}
public int Commit()
{
return this.context.SaveChanges();
}
public void Dispose()
{
this.context.Dispose();
}
}
using (IRepository<Contact> e = new SqlRepository<Contact>(new AppointmentReminderDb()))
{
e.Add(new Contact() { Active = true });
e.Add(new Contact() { Active = true });
e.Commit();
var count = await e.FindAll().Count(); // do not get Count property
}
In the above line of code, I don't understand why I am not getting Count property. Instead I get CountAsynch. I really want to simply get Count property.
My IQueryable for FindAll is correctly defined in the interface and in the class method.
You may have forgotten to include the right namespace.
The method you're seeing in IntelliSense is named QueryableExtensions.CountAsync<TSource> defined in the System.Data.Entity namespace, which returns Task<int> and, as such, should be awaited.
The method (not property) you're looking for is named Queryable.Count<T>() and is defined in the System.Linq namespace. It returns an int and should not be awaited.
If the operation involves IO, which it probably does, you want to use CountAsync.
I want to create a common database abstraction in order to expose the same interface without worrying about the type of the DbContext that the database manage.
Here there is an example in order to explain well the concept:
public interface IDatabase<T> where T : DbContext {
void Add<T>(T entity);
void Remove<T>(T entity);
void SaveChanges();
}
The implementation can be:
public MyDatabase<T> : IDatabase<T> where T : MyContext {
public T Context { get; private set; }
//singleton contructor ...
public void Add<TC>(TC entity) {
Context.Set<TC>().Add(entity);
}
public void Remove<TC>(TC entity) {
Context.Set<TC>().Add(entity);
}
public void SaveChanges {
Context.SaveChanges();
}
}
The goals of this design are different: expose the same interface in order to decouple logic from database, change quickly the database (context), create one time the context and reuse during all the application lifetime (lock mechanism are required).
The problem is that the interface hides all the types of the sets in the context.
Context.Set<TC>().Add(entity); //this line don't compile
I'm not sure that this design is the best practise. How can I implement a design that offers these features?
Why you does not use the standard pattern for example Repository pattern you can also combine it with UnitOfWork.
You make it complicated for your self, just check this.
public interface IMyClassRepository : IDisposable
{
IQueryable<MyClass> All { get; }
IQueryable<MyClass> AllIncluding(params Expression<Func<MyClass, object>>[] includeProperties);
MyClass Find(int id);
void InsertOrUpdate(MyClass myClass);
void Delete(int id);
void Save();
}
public class MyClassRepository : IMyClassRepository
{
DBContext context = new DBContext();
public IQueryable<MyClass> All
{
get { return context.Employees; }
}
public IQueryable<MyClass> AllIncluding(params Expression<Func<MyClass, object>>[] includeProperties)
{
IQueryable<MyClass> query = context.MyClasses;
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public MyClass Find(int id)
{
return context.MyClasses.Find(id);
}
public void InsertOrUpdate(MyClass myClass)
{
if (myClass.Id == default(int))
{
// New entity
context.MyClasses.Add(myClass);
}
else
{
// Existing entity
context.Entry(myClass).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var employee = context.Employees.Find(id);
context.Employees.Remove(employee);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public class MyClass
{
}
I read all the similar titles questions, but i didn't find the answer to my problem, so I open a new question:
I have two mysql tables:
tb1 (int_id, code, description, ..., my_id);
tb2 (int_id, code, description, ..., tb1_id);
I create a generic repository to manage DbContext and GetAll, GetById, GetByLambda, Insert, Update and Delete methode.
namespace Model.DataAccessLayer
{
public class Repository<T> : IRepository<T> where T : EntityObject, IEntity
{
protected DbContext dbContext = null;
public virtual DbContext DbContext
{
get { return dbContext; }
set { dbContext = value; }
}
public ObjectContext ObjectContext
{
get { return ((IObjectContextAdapter)DbContext).ObjectContext; }
}
public void Dispose()
{
ObjectContext.Dispose();
System.GC.SuppressFinalize(this);
}
public virtual IQueryable<T> GetAll()
{
return ObjectContext.CreateObjectSet<T>();
}
public virtual IEnumerable<T> GetByLambda(Func<T, bool> p)
{
return GetAll().Where(p);
}
public virtual void Save()
{
DbContext.SaveChanges();
}
...
}
}
and the inherited class which I used:
namespace Model.DataAccessLayer
{
public class RepositoryP<T> : Repository<T> where T : EntityObject, IEntity
{
public myEntities MyContext
{
get { return (myEntities)ObjectContext; }
//set { ObjectContext = value; }
}
public override DbContext DbContext
{
get
{
if (dbContext == null)
{
dbContext = new DbContext("myEntities");
}
return dbContext;
}
set
{
base.DbContext = value;
}
}
}
}
It works great when using only one table.
When I try to use my two tables and the foreign key relation between them, it doesn't work.
For example I try to get all records from table tb2 where tb1.my_id=5 with the following join tb1.int_id = tb2.tb1_id.
List<tb2> lj = new Tb2DAO().GetByLambda(l => l.tb1.my_id == 5).ToList();
(Tb2DAO inherited from my generic repository class.)
I have the following MySQL error:
"MySql.Data.MySqlClient.MySqlException: There is already an open DataReader associated with this Connection which must be closed first."
I think this comes from my DbContext which is not common to my two tables entities.
So I tried to implement the UnitOfWork Pattern to solve this problem, like this:
namespace Model.DataAccessLayer
{
public class UnitOfWork : IDisposable
{
private DbContext dbContextUnit = null; //= new DbContext();
private Tb1DAO tb1DAO;
private Tb2DAO tb2DAO;
public Tb1DAO tb1
{
get
{
if (this.tb1DAO == null)
{
if (dbContextUnit != null)
{
this.tb1DAO = new Tb1DAO { DbContext = dbContextUnit };
}
else
{
this.tb1DAO = new Tb1DAO();
dbContextUnit = this.tb1DAO.DbContext;
}
}
return tb1DAO;
}
}
public Tb2DAO tb2
{
get
{
if (this.tb2DAO == null)
{
if (dbContextUnit != null)
{
this.tb2DAO = new Tb2DAO { DbContext = dbContextUnit };
}
else
{
this.tb2DAO = new Tb2DAO();
dbContextUnit = this.tb2DAO.DbContext;
}
}
return tb2DAO;
}
}
public void Save()
{
dbContextUnit.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
dbContextUnit.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
And now in my code I tried to use the Unit of Work like this :
UnitOfWork unitOfWork = new UnitOfWork();
List<tb2> tb2List = unitOfWork.tb2.GetByLambda(l => l.index_job.job_id == job_id).ToList();
But I have always the same error message :
"MySql.Data.MySqlClient.MySqlException: There is already an open DataReader associated with this Connection which must be closed first."
is there something I am doing wrong ? Please can you help me ? This notion of repository and unit Of work are new for me
and I am confused else I read lot of think about it may be not the right one...
I also to try to add MultipleActiveResultSets=true to my connection but it is not recognized.
many thank to all & regards,
wst
Your GetByLambda() method is calling GetAll() which creates a new context using ObjectContext.CreateObjectSet<T>(). So you now have more than one context open. I would advise using the standard EF associations and the repository pattern, then you can avoid this entire mess. Here is a link that may help you get started - http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-code-first-walkthrough.aspx.
I'm not sure about this method
public virtual IQueryable<T> GetAll()
{
return ObjectContext.CreateObjectSet<T>();
}
It's create new object set about which EF context doesn't know.
You can try to pass Func<ObjectContext, ObjectResult<T>> from derived class to base. (It should return ObjectResult which are got from EF context. F.e. context => context.Entities).