Here is a image from the ANTS memory profiler. It seens that there are a lot of objects hold in memory. How can I find what I am doing wrong?
**UPDATE**
Here is my repository classes:
public class Repository<T> : IRepository<T> where T : class, IDataEntity
{
ObjectContext _context;
IObjectSet<T> _objectSet;
readonly string _entitySetName;
readonly string[] _keyNames;
private ObjectContext Context
{
get
{
if (_context == null)
{
_context = GetCurrentUnitOfWork<EFUnitOfWork>().Context;
}
return _context;
}
}
private IObjectSet<T> ObjectSet
{
get
{
if (_objectSet == null)
{
_objectSet = this.Context.CreateObjectSet<T>();
}
return _objectSet;
}
}
public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>() where TUnitOfWork : IUnitOfWork
{
return (TUnitOfWork)UnitOfWork.Current;
}
public virtual IEnumerable<T> GetQuery()
{
return ObjectSet;
}
public virtual IEnumerable<T> GetQuery(params Expression<Func<T, object>>[] includes)
{
return ObjectSet.IncludeMultiple(includes);
}
public virtual IEnumerable<T> GetQuery(
IEnumerable<Expression<Func<T, bool>>> filters,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy,
IEnumerable<Expression<Func<T, object>>> includes)
{
IQueryable<T> _query = ObjectSet;
if (filters != null)
{
foreach (var filter in filters)
{
_query = _query.Where(filter);
}
}
if (includes != null && includes.Count() > 0)
{
_query = _query.IncludeMultiple(includes.ToArray());
}
if (orderBy != null)
{
_query = orderBy(_query);
}
return _query;
}
public virtual IPaged<T> GetQuery(
IEnumerable<Expression<Func<T, bool>>> filters,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy,
int pageNumber, int pageSize,
IEnumerable<Expression<Func<T, object>>> includes)
{
IQueryable<T> _query = ObjectSet;
if (filters != null)
{
foreach (var filter in filters)
{
_query = _query.Where(filter);
}
}
if (orderBy != null)
{
_query = orderBy(_query);
}
IPaged<T> page = new Paged<T>(_query, pageNumber, pageSize, includes);
return page;
}
public virtual void Insert(T entity)
{
this.ObjectSet.AddObject(entity);
}
public virtual void Delete(T entity)
{
if (entity is ISoftDeletable)
{
((ISoftDeletable)entity).IsDeleted = true;
//Update(entity);
}
else
{
this.ObjectSet.DeleteObject(entity);
}
}
public virtual void Attach(T entity)
{
ObjectStateEntry entry = null;
if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == false)
{
this.ObjectSet.Attach(entity);
}
}
public virtual void Detach(T entity)
{
ObjectStateEntry entry = null;
if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == true)
{
this.ObjectSet.Detach(entity);
}
}
}
Now, if I have class A that holds records from table A, I also create class:
public class ARepository:BaseRepository<A> {
// Implementation of A's queries and specific db operations
}
Here is my EFUnitOfWork class:
public class EFUnitOfWork : IUnitOfWork, IDisposable
{
public ObjectContext Context { get; private set; }
public EFUnitOfWork(ObjectContext context)
{
Context = context;
context.ContextOptions.LazyLoadingEnabled = true;
}
public void Commit()
{
Context.SaveChanges();
}
public void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
GC.SuppressFinalize(this);
}
}
And UnitOfWork class:
public static class UnitOfWork
{
private const string HTTPCONTEXTKEY = "MyProj.Domain.Business.Repository.HttpContext.Key";
private static IUnitOfWorkFactory _unitOfWorkFactory;
private static readonly Hashtable _threads = new Hashtable();
public static void Commit()
{
IUnitOfWork unitOfWork = GetUnitOfWork();
if (unitOfWork != null)
{
unitOfWork.Commit();
}
}
public static IUnitOfWork Current
{
get
{
IUnitOfWork unitOfWork = GetUnitOfWork();
if (unitOfWork == null)
{
_unitOfWorkFactory = ObjectFactory.GetInstance<IUnitOfWorkFactory>();
unitOfWork = _unitOfWorkFactory.Create();
SaveUnitOfWork(unitOfWork);
}
return unitOfWork;
}
}
private static IUnitOfWork GetUnitOfWork()
{
if (HttpContext.Current != null)
{
if (HttpContext.Current.Items.Contains(HTTPCONTEXTKEY))
{
return (IUnitOfWork)HttpContext.Current.Items[HTTPCONTEXTKEY];
}
return null;
}
else
{
Thread thread = Thread.CurrentThread;
if (string.IsNullOrEmpty(thread.Name))
{
thread.Name = Guid.NewGuid().ToString();
return null;
}
else
{
lock (_threads.SyncRoot)
{
return (IUnitOfWork)_threads[Thread.CurrentThread.Name];
}
}
}
}
private static void SaveUnitOfWork(IUnitOfWork unitOfWork)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items[HTTPCONTEXTKEY] = unitOfWork;
}
else
{
lock(_threads.SyncRoot)
{
_threads[Thread.CurrentThread.Name] = unitOfWork;
}
}
}
}
Here is how I use this:
public class TaskPriceRepository : BaseRepository<TaskPrice>
{
public void Set(TaskPrice entity)
{
TaskPrice taskPrice = GetQuery().SingleOrDefault(x => x.TaskId == entity.TaskId);
if (taskPrice != null)
{
CommonUtils.CopyObject<TaskPrice>(entity, ref taskPrice);
}
else
{
this.Insert(entity);
}
}
}
public class BranchRepository : BaseRepository<Branch>
{
public IList<Branch> GetBranchesList(Guid companyId, long? branchId, string branchName)
{
return Repository.GetQuery().
Where(b => companyId == b.CompanyId).
Where(b => b.IsDeleted == false).
Where(b => !branchId.HasValue || b.BranchId.Equals(branchId.Value)).
Where(b => branchName == null || b.BranchName.Contains(branchName)).
ToList();
}
}
[WebMethod]
public void SetTaskPrice(TaskPriceDTO taskPrice)
{
TaskPrice tp = taskPrice.ToEntity();
TaskPriceRepository rep = new TaskPriceRepository();
rep.Set(tp);
UnitOfWork.Commit();
}
[WebMethod]
public IList<Branch> GetBranchesList()
{
BranchRepository rep = new BranchRepository();
return rep.GetBranchesList(m_User.UserCompany.CompanyId, null, null).ToList();
}
I hope this is enough info to help me solving the problem. Thanks.
UPDATE 2
There is also UnitOfWorkFactory that initializes UnitOfWork:
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
private static Func<ObjectContext> _objectContextDelegate;
private static readonly Object _lockObject = new object();
public static void SetObjectContext(Func<ObjectContext> objectContextDelegate)
{
_objectContextDelegate = objectContextDelegate;
}
public IUnitOfWork Create()
{
ObjectContext context;
lock (_lockObject)
{
context = _objectContextDelegate();
}
return new EFUnitOfWork(context);
}
}
In order to use this, in the application startup I use structuremap:
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWorkFactory>().Use<UnitOfWorkFactory>();
x.For(typeof(IRepository<>)).Use(typeof(Repository<>));
});
I have a hunch you don't dispose the context.
I suggest disposing the context whenever you done interacting with database.
Use using statement whenever you create the context.
[Edit]
As far as I can see, you cache and don't dispose your EFUnitOfWork object. It is disposable, which is correct, but I don't see when disposable is called. Seems like you hold a reference to the context for all application run time. Moreover, you create and hold one context per thread, which will make it even worse.
I can't tell you for sure where you should put Dispose or using, as I don't know the usages.
You could put it probably to your Commit method, but I don't know if the Commit called only once during database interaction session.
Also, your design might be overcomplicated.
If I were you, I would:
Find the way to dispose the context using current code, as a short-term solution
Simplify the design, as the long-term solution
If I had time I would do long-term solution right away.
But again, I can't tell if the complexity of your design is justified, as I don't know how big your application is and what it does and what the requirements are.
Couple of things come to my mind:
You aren't probably Disposing the ObjectContext. Make sure all your database codes are within using(var context = CreateObjectContext()) block
You have an N-tier architecture and you are passing entities from the data access layer to upper layer without Detaching the entities from ObjectContext. You need to call ObjectContext.Detach(...)
You are most likely returning a full collection of entities, instead of returning a single enity for single Get operations. For ex, you have queries like from customer in context.Customers select customer instead of doing from customer in context.Customers select customer.FirstOrDefault()
I have had hard time making Entity Framework to work in an N-tier application. It's just not suitable for using in N-tier apps as is. Only EF 4.0 is. You can read about all my adventure in making EF 3 work in an N-tier app.
http://www.codeproject.com/KB/linq/ef.aspx
Does this answer your question?
Do you clear the ObjectContext once in a while. If you keep an ObjectContext alive for a long time this will consume memory related to the size of the EntityDataModel and the number of Entities loaded into this ObjectContext.
I had the same problem in a class which uses dependency injection, so the using() option was not an alternative. My solution was to add DbContextOptions<Context> to the constructor and as a private field to the class. Then, you can call
_db.Dispose();
_db = new BlockExplorerContext(_dBContextOptions);
at appropriate times. This fixed my problem where I was running out of RAM and the application was killed by the OS.
Related
I am wondering, how we can handle a situation, and if I'm going about this the wrong way. We wrote a web application based on one ERP's database schema model. We are using Entity Framework for the system, with the regular dependency injection method.
Now that we have purchased multiple ERP's from other labs, we are trying to allow their data be used on our first original web portal built for our original ERP. As you can imagine, this is rough as the database models and design will not line up with ours. For example something like GetAllAssets() stored procedure returns the complex type and then is bound to the repo level, the service level and onto the view.
What I was thinking is that we could maybe add multiple EDMX (context for databases), then keep everything from the Views to the controllers to the service layer the same. At the service layer, and type params to our classes, and so we could pass the context the current user logged in as, and then in auto mapper add new entries for the new database context calls from Entity Framework, to map to our original code from the service back down to the view.
Is this possible, and or a good idea or bad idea?
Here is a example of a current basic controller we are using with DI style, and I have removed a lot of code for this question's example:
[AuthorizeWithSession]
public class LocationController : Controller
{
private readonly IMProAssetLocationService _mProAssetLocationService;
private readonly IUIDataService _uiDataService;
public LocationController(IMProAssetLocationService mProAssetLocationService,
IUIDataService uiDataService)
{
_mProAssetLocationService = mProAssetLocationService;
}
public ActionResult List()
{
return View();
}
public ActionResult List2()
{
return View();
}
public ActionResult GetLocationList([DataSourceRequest]DataSourceRequest request)
{
//var result = DepartmentService.GetDepartmentList(SessionHelper.GetCustId());
var result = _mProAssetLocationService.MProAssetLocationGetLocationByCustID(SessionHelper.GetCustId(), null);
if (result != null && result.Any())
{
return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
}
}
The interface service layer:
public interface IMProAssetLocationService
{
IEnumerable<LocationVm> MProAssetLocationGetLocationByCustID(string custId,string id);
string MProAssetLocationInsertLocation(LocationVm vm);
void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
void MProAssetLocationUpdateLocationByCustIDAndLocationID(LocationVm vm);
}
The service layer:
public class MProAssetLocationService : LogManager, IMProAssetLocationService
{
private readonly IMProAssetLocationRepo _mProAssetLocationRepo;
public MProAssetLocationService(IMProAssetLocationRepo mProAssetLocationRepo)
{
_mProAssetLocationRepo = mProAssetLocationRepo;
}
protected override Type LogPrefix
{
get { return this.GetType(); }
}
public IEnumerable<LocationVm> MProAssetLocationGetLocationByCustID(string custId, string id)
{
List<LocationVm> listlocationVm = new List<LocationVm>();
try
{
var records = _mProAssetLocationRepo.MProAssetLocationGetLocationByCustID(custId,id);
}
}
The Interface repo layer:
public interface IMProAssetLocationRepo : IRepository<MProAssetLocation>
{
IEnumerable<string> GetMProAssetLocatonByCustId(string custId);
IEnumerable<string> GetMProAssetLocatonDescriptionByCustId(string custId);
IEnumerable<LocationView> GetMProAssetLocatonListByCustId(string search, string locationID, string custId);
IEnumerable<LocationView> MProAssetLocationGetLocationByCustID(string custId, string id);
string MProAssetLocationInsertLocation(LocationView lv);
void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
void MProAssetLocationUpdateLocationByCustIDAndLoacationID(LocationView lv);
}
The repo layer:
public class CalLocationsRepo : RepositoryBase<CalLocaton>, ICalLocationsRepo
{
public CalLocationsRepo(IDbFactory dbFactory)
: base(dbFactory)
{
}
//WHERE CalCodeActive=1 AND CalCodeGroup='OSS' ORDER BY CalCode
public IEnumerable<string> GetCalLocations(string empID)
{
return DbContext.TAM_GetCalLocationsList(empID).ToList();
}
}
I was thinking of something like using a context type in our system. I know the entity models calls would be named differently based on our different databases using their own stored procedures, but thought at the level prior to the call i check the context to use, then make the call accordingly like so:
public class DBContextRepo<T> : RepositoryBase, IDBContextRepo<T>
{
DBContextRepo<T> _typeParameterClass;
public DBContextRepo(IDbFactory dbFactory, DBContextRepo<T> typeParameterClass)
: base(dbFactory)
{
_typeParameterClass = typeParameterClass;
}
public List<string> GetAllModelsByManufcaturer(string manufacturerName)
{
List<string> results = new List<string>();
if (_typeParameterClass.GetType() == typeof(TAM.DataLayer.EntityModels.QuoteWerks1Entities))
{
using(var dbContext = DbContextQw)
{
var items = dbContext.Products_OurProducts_Products.Where(p => p.Manufacturer == manufacturerName).ToList();
results = items.Select(p => p.ManufacturerPartNumber).ToList();
}
}
else
{
using (var dbContext = DbContext)
{
var items = dbContext.Models.Where(a => a.Manufacturer.MfrName == manufacturerName);
results = items.Select(m => m.ModelNumber).ToList();
}
}
return results;
}
}
This causes errors and is where im not sure how to handle two DBContext:
public class DbFactory : Disposable, IDbFactory
{
private TAMModel _dbContext;
private QuoteWerks1Entities _dbContextQW;
public TAMModel Init()
{
return _dbContext ?? (_dbContext = new TAMModel());
}
public QuoteWerks1Entities InitQW()
{
return _dbContextQW ?? (_dbContextQW = new QuoteWerks1Entities());
}
protected override void DisposeCore()
{
if (_dbContext != null)
{
_dbContext.Dispose();
}
if (_dbContextQW != null)
{
_dbContextQW.Dispose();
}
}
}
Once i added the second context, all of my regular code say they do not have a corresponding type in constructors such as this one:
public class ContractRepo : RepositoryBase<Contract>, IContractRepo
{
public ContractRepo(IDbFactory dbFactory)
: base(dbFactory)
{
}
public string GetContractIdentifyByCustId(string custId)
{
return DbContext.TAM_GetContractIdentifyByCustId(custId).SingleOrDefault();
}
}
Here is the BaseRepo class:
public class RepositoryBase
{
private readonly TAMModel _dataContext;
private readonly QuoteWerks1Entities _dataContextQW;
protected IDbFactory DbFactory { get; private set; }
protected TAMModel DbContext
{
get
{
return _dataContext ?? DbFactory.Init();
}
}
protected QuoteWerks1Entities DbContextQw
{
get
{
return _dataContextQW ?? DbFactory.InitQW();
}
}
protected RepositoryBase(IDbFactory dbFactory)
{
DbFactory = dbFactory;
}
}
public abstract class RepositoryBase<T> where T : class
{
private readonly TAMModel _dataContext;
private readonly IDbSet<T> _dbSet;
private readonly IDbSet<T> _dbSetQW;
private readonly QuoteWerks1Entities _dataContextQW;
protected IDbFactory DbFactory { get; private set; }
protected TAMModel DbContext
{
get
{
return _dataContext ?? DbFactory.Init();
}
}
protected QuoteWerks1Entities DbContextQW
{
get
{
return _dataContextQW ?? DbFactory.InitQW();
}
}
protected RepositoryBase(IDbFactory dbFactory, T type)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
_dbSetQW = DbContextQW.Set<T>();
}
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
DbContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = _dbSet.Where<T>(where);
foreach (T obj in objects)
{
_dbSet.Remove(obj);
}
}
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual T GetById(string id)
{
return _dbSet.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).SingleOrDefault();
}
public virtual IQueryable<T> Query()
{
return _dbSet;
}
public virtual IQueryable<T> Query(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where);
}
public virtual ObjectQuery<U> CreateQuery<U>(string query, ObjectParameter[] parameters)
{
return CastAsObjectContext().CreateQuery<U>(query, parameters);
}
public virtual ObjectQuery<U> CreateQuery<U>(string query)
{
return CreateQuery<U>(query, new ObjectParameter[0] { });
}
public virtual ObjectQuery<DbDataRecord> CreateQuery(string query, ObjectParameter[] parameters)
{
return CreateQuery<DbDataRecord>(query, parameters);
}
public virtual ObjectQuery<DbDataRecord> CreateQuery(string query)
{
return CreateQuery<DbDataRecord>(query);
}
private ObjectContext CastAsObjectContext()
{
var oContext = (DbContext as IObjectContextAdapter).ObjectContext;
return oContext;
}
}
The only problem is, how do I set the context on a login when using dependency injection? Will this work, as at the moment I'm still in the process, or am I over complicating it and going about it the wrong way? Thanks in advance.
It's a week I have been dealing with Repository pattern, somehow I have implemented something, a generic repository:
private CentralEntities db = null;
private DbSet<T> table = null;
public RepositoryTest()
{
this.db = new CentralEntities();
table = db.Set<T>();
}
public RepositoryTest(CentralEntities db)
{
this.db = db;
table = db.Set<T>();
}
public IEnumerable<T> SelectAll()
{
return table.Take(10).ToList();
}
Here is my IRepository:
public interface IRepositoryTest<T> where T:class
{
IEnumerable<T> SelectAll();
}
Here in my Controller I implemented like the following and it works:
public class DashbrdController : Controller
{
IRepositoryTest<Event> _repository = null;
public DashbrdController(IRepositoryTest<Event> _repository)
{
this._repository = _repository;
}
public DashbrdController()
{
this._repository = new RepositoryTest<Event>();
}
public ActionResult DashBrd()
{
var rslt= _repository.SelectAll().Take(10);
return View(rslt);
}
}
First I do not how to implement Iunitofwork and UnitOfWork, and second apart from creating a single gate for update or insert, whats the usage of UnitOfWork? what kind of problem can it solve in the above example?
Please refer to the section below for detail understanding of UOW and Repository:
1) You create Generic Repository (The base of all the data source):
public class GenericRepository : IGenericRepository where T :
class
{
protected DbContext _entities;
protected readonly IDbSet<T> _dbset;
public GenericRepository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable();
}
public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IEnumerable<T> query = _dbset.Where(predicate).AsEnumerable();
return query;
}
public virtual T GetSingle(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
T query = _dbset.Where(predicate).FirstOrDefault();
return query;
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = EntityState.Modified;
}
public virtual void Attach(T entity)
{
_dbset.Attach(entity);
}
public virtual void Save()
{
_entities.SaveChanges();
}
}
2) Then you create a Unit Of Work (Generic that adds the instance of Repository)
public sealed class GenericUnitOfWork : IGenericUnitOfWork, IDisposable
{
private ApplicationDbContext entities = null;
private ApplicationUserManager _userManager;
public GenericUnitOfWork()
{
entities = new ApplicationDbContext();
}
public Dictionary<Type, object> repositories = new Dictionary<Type, object>();
public IGenericRepository<T> Repository<T>() where T : class
{
if (repositories.Keys.Contains(typeof(T)) == true)
{
return repositories[typeof(T)] as IGenericRepository<T>;
}
IGenericRepository<T> repo = new GenericRepository<T>(entities);
repositories.Add(typeof(T), repo);
return repo;
}
public int Commit()
{
return entities.SaveChanges();
}
private bool disposed = false;
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
entities.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
3) Then you call UnitOfWork from your controller, that creates instance of Repository in Generic Form
public class DashbrdController : Controller
{
private GenericUnitOfWork uow = null;
public DashbrdController()
{
uow = new GenericUnitOfWork();
}
public ActionResult DashBrd()
{
var rslt = uow.Repository<Event>().GetAll().ToList();
return View(rslt);
}
}
The unit of work class coordinates the work of multiple repositories by creating a single database context class shared by all of them.
For a specific user action (say adding a event), all the transactions like insert/update/delete and so on are done in one single transaction, rather then doing multiple database transactions. This means, one unit of work here involves insert/update/delete operations, all in one single transaction.
Please make the interfaces with the implementation classes provided above. Let me know if problem occurs in that.
Hope if helps.
I am working on crud operations in mvc 4.0 with unitofwork and generic repository with Ninject for DI.
I am able to get a particular record from a table, I am even able to get all the records from the table.
but I am not able to insert a new record in the database table. I am not getting any error/exception and it is running each statement
cleanly but there is no effect in database below is my controller where I am using the repository and unitof work.
Can somebody tell me where I am wron or what code/statements I have left in this code. I ahve checked it lot of time and I am stucked now.
Not getting the problem
Controller:
private IUnitOfWork _unitOfWork;
private IRepository<tbl_Employee> _Repo;
private IRepository<tbl_Department> _Department;
public HomeController( IUnitOfWork UOW, IRepository<tbl_Employee> Repository, IRepository<tbl_Department> Depart)
{
this._unitOfWork = UOW;
this._Repo = Repository;
this._Department = Depart;
}
//This runs successfully and gets all the records in the view page and I am displaying all records using foreach in div structure
public ActionResult Index()
{
EmployeeModel ObjModel = new EmployeeModel();
ObjModel.Employees = this._Repo.GetALL();
//ObjModel.Employees = this._Employee.GetEmployees();
return View(ObjModel);
}
//This also runs successfully and it brought me a single record on selection of particular record from employee listing.
public ActionResult EmployeeDetail(string id)
{
EmployeeDetailModel ObjModel = new EmployeeDetailModel();
if (!string.IsNullOrEmpty(id))
{
var Employee = this._Repo.Find(Convert.ToInt32(id));
if (Employee != null)
{
ObjModel.InjectFrom(Employee);
}
}
return View(ObjModel);
}
// Here is the problem . Not able to insert the record. The model object is not empty . I have checked it and there is no error.It brought me a message
"Employee Created Successfully but in database there is no record.
public ActionResult SaveEmployee(EmployeeDetailModel Model)
{
string Msg = string.Empty;
try
{
tbl_Employee ObjEmployee = new tbl_Employee();
ObjEmployee.InjectFrom(Model);
if (Model.Male)
{
ObjEmployee.Sex = "m";
}
else
{
ObjEmployee.Sex = "f";
}
ObjEmployee.Department_Id = Model.Dept_id;
ObjEmployee.Salary = Convert.ToInt32(Model.Salary);
this._Repo.Insert(ObjEmployee);
this._unitOfWork.Commit();
Msg = "Employee Created Successfully";
}
catch
{
Msg = "Error occurred while creating the employee, Please try again.";
}
return Json(new { Message = Msg });
}
/// Repository interface
public interface IRepository<T> where T : class
{
void Insert(T entity);
void Delete(T entity);
void Update(T entity);
T Find(int key);
IEnumerable<T> GetALL();
}
Repository class
public class Repository<T> : Connection, IRepository<T> where T : class
{
private readonly DbSet<T> _dbSet;
public Repository()
{
_dbSet = _dbContext.Set<T>();
}
public void Insert(T entity)
{
_dbSet.Add(entity);
}
public void Delete(T entity)
{
_dbSet.Remove(entity);
}
public void Update(T entity)
{
var updated = _dbSet.Attach(entity);
_dbContext.Entry(entity).State = EntityState.Modified;
//_dataContext.Entry(item).State = EntityState.Modified;
}
public T Find(int Key)
{
var dbResult = _dbSet.Find(Key);
return dbResult;
}
public IEnumerable<T> GetALL()
{
return _dbSet;
}
}
UnitofWork Interface
public interface IUnitOfWork : IDisposable
{
void Commit();
}
Unit of work class
public class UnitOfWork : Connection, IUnitOfWork
{
private bool _disposed;
public void Commit()
{
_dbContext.SaveChanges();
}
public void Dispose()
{
Dispose(true);
// Take yourself off the Finalization queue to prevent finalization code for object from executing a second time.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!_disposed)
{
// If disposing equals true, dispose all managed and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
if (_dbContext != null)
{
_dbContext.Dispose();
}
}
}
_disposed = true;
}
}
My UnitofWork and Repository class derives from connection class where dbcontext is defined.
public abstract class Connection
{
protected db_TestEntities _dbContext;
public Connection()
{
this._dbContext = new db_TestEntities();
}
}
Is it that my dbContext is creating a new instance everytime like explained Here
and if yes then how can I resolve it.
tbl_Employee ObjEmployee = new tbl_Employee();
ObjEmployee.InjectFrom(Model);
if (Model.Male)
{
ObjEmployee.Sex = "m";
}
else
{
ObjEmployee.Sex = "f";
}
ObjEmployee.Department_Id = Model.Dept_id;
ObjEmployee.Salary = Convert.ToInt32(Model.Salary);
this._Repo.Insert(ObjEmployee);
After this, you should see your object mapped by EF in local memory.
this._unitOfWork.Commit();
Here your object should be pushed to database. dbContext.SaveChanges() return number of changed records which should be in your case 1.
Msg = "Employee Created Successfully";
Update:
So the problem is in your Connection class as you suggested.
I would create your DbContext in one place and then pass it to repository and unit of work. You could also create DbContext in unit of work constructor and then pass UOW to repository. This is one of my older implementation of this:
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
private ForexDbContext dbContext;
internal ForexDbContext DbContext
{
get { return dbContext ?? (dbContext = new ForexDbContext()); }
}
internal DbSet<T> Set<T>()
where T : class
{
return DbContext.Set<T>();
}
public void Dispose()
{
if(dbContext == null) return;
dbContext.Dispose();
dbContext = null;
}
public void SaveChanges()
{
int result = DbContext.SaveChanges();
}
public ITransaction BeginTransaction()
{
return new EntityFrameworkTransaction(DbContext.BeginTransaction());
}
}
public class ContactsRepositoryWithUow : IRepository<Contact>
{
private SampleDbEntities entities = null;
public ContactsRepositoryWithUow(SampleDbEntities _entities)
{
entities = _entities;
}
public IEnumerable<Contact> GetAll(Func<Contact, bool> predicate = null)
{
if (predicate != null)
{
if (predicate != null)
{
return entities.Contacts.Where(predicate);
}
}
return entities.Contacts;
}
public Contact Get(Func<Contact, bool> predicate)
{
return entities.Contacts.FirstOrDefault(predicate);
}
public void Add(Contact entity)
{
entities.Contacts.AddObject(entity);
}
public void Attach(Contact entity)
{
entities.Contacts.Attach(entity);
entities.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
}
public void Delete(Contact entity)
{
entities.Contacts.DeleteObject(entity);
}
}
Please find answer in below link for more details
Crud Operation with UnitOfWork
I have the following layers in my application.
Repository.Ef (this handle the context of ef)
Entities (here is all entities for ef)
Core (This layer handle all business and works like a wrapper
between Ef <> Gui)
Gui (This is the User interface)
I have interface for most of the classes and use DI, but this version is compressed to only show the classes.
This is the UnitOfWork, that hold the DbContext in my Repository.Ef layer.
public class UnitOfWork : DbContext, IUnitOfWork
{
static UnitOfWork()
{
Database.SetInitializer<UnitOfWork>(null);
}
public UnitOfWork()
: base("Name=SalesDb")
{
}
public IRepository<T> Repository<T>() where T : EntityBase
{
return new Repository<T>(Set<T>());
}
public void ApplyStateChanges()
{
foreach (var dbEntityEntry in ChangeTracker.Entries())
{
var entityState = dbEntityEntry.Entity as EntityBase;
if (entityState == null)
throw new InvalidCastException("All entites must implement the IObjectState interface, " +
"this interface must be implemented so each entites state can explicitely determined when updating graphs.");
dbEntityEntry.State = StateHelper.ConvertState(entityState.State);
}
}
#region DBSET
// HERE IS ALL MY DBSETS
#endregion
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public override int SaveChanges()
{
ApplyStateChanges();
return base.SaveChanges();
}
}
And this is my Repository (same layer as UnitOfWork)
public class Repository<T> : IRepository<T> where T : class, IEntity
{
private readonly DbSet<T> _dbSet;
public Repository(DbSet<T> dbSet)
{
_dbSet = dbSet;
}
public IQueryable<T> Query()
{
var data = _dbSet.AsQueryable();
return data;
}
public IEnumerable<T> GetAll()
{
return _dbSet;
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dbSet.Where(predicate);
}
public T FindById(int id)
{
return _dbSet.Find(id);
}
public void Add(T entity)
{
entity.State = ObjectState.Added;
_dbSet.Add(entity);
}
public void Remove(T entity)
{
entity.State = ObjectState.Deleted;
_dbSet.Remove(entity);
}
public void Update(T entity)
{
entity.State = ObjectState.Modified;
_dbSet.Attach(entity);
}
}
Here is my Core layer (Business rules and the wrapper between GUI layer)
The following is my ServiceUnit.
public class ServiceUnit
{
internal readonly IUnitOfWork unitOfWork;
public ServiceUnit()
{
unitOfWork = new UnitOfWork();
}
public void Add<T>(T entity, int marketId, string username) where T : EntityBase
{
entity.MarketId = marketId;
entity.ChUser = username;
entity.ChTime = DateTime.Now;
entity.Deleted = false;
unitOfWork.Repository<T>().Add(entity);
unitOfWork.SaveChanges();
}
public void Update<T>(T entity, string username) where T : EntityBase
{
entity.ChUser = username;
entity.ChTime = DateTime.Now;
unitOfWork.Repository<T>().Update(entity);
unitOfWork.SaveChanges();
}
public void Remove<T>(int id) where T : EntityBase
{
var entity = unitOfWork.Repository<T>().FindById(id);
entity.Deleted = true;
entity.ChTime = DateTime.Now;
unitOfWork.Repository<T>().Update(entity);
unitOfWork.SaveChanges();
}
public IEnumerable<T> Find<T>(int? marketId = null, Expression<Func<T, bool>> predicate = null) where T : EntityBase
{
var data = unitOfWork.Repository<T>()
.Find(predicate);
if (marketId != null)
{
data = data
.Where(t => t.MarketId == marketId);
}
return data;
}
public T FindById<T>(int id) where T : EntityBase
{
return unitOfWork.Repository<T>().FindById(id);
}
public void Commit()
{
unitOfWork.SaveChanges();
}
}
And this is a Service class to handle all Contact functions
public class ContactService
{
private readonly ServiceUnit serviceUnit;
private IRepository<Contact> contactRep
{
get { return serviceUnit.unitOfWork.Repository<Contact>(); }
}
private IRepository<ContactUserProfile> contactUserProfileRep
{
get { return serviceUnit.unitOfWork.Repository<ContactUserProfile>(); }
}
public ContactService(ServiceUnit serviceUnit)
{
this.serviceUnit = serviceUnit;
}
public IEnumerable<ContactUserProfile> GetContactsForUser(int marketId, int userId, int status)
{
return contactUserProfileRep
.Query()
.Where(u => u.Contact.MarketId == marketId)
.Where(cup => cup.UserProfileId == userId)
.Where(c => c.Deleted == false)
.Where(c => c.Contact.Status == status)
.ToList();
}
}
Lets explain how i use all this code.
First of all, i dont want to have dependency for entity framework in my gui layer, and with this service wrapper (ServiceUnit) i dont have to reference entity framework.
Every page request create a ServiceUnit, and the ServiceUnit create a new UnitOfWork that hold whole the EntityFramework context.
For example, the contact page create a ServiceUnit and a ServiceContact and inject the Service unit, so i have the same context for the request.
Can this pattern cause any problem? Just want to se if i missed something importent here.
Do you need the "ServiceUnit" class? Why not use the UnitOfWork directly in your services?
What I'd suggest is basically to have have four projects:
Data Access Layer Project: EF DbContext, Repositories, UnitOfWork. References "Entities" project.
Entities Project: EF entities (if you want to share the EF entities
throughout the solution). Doesn't reference any other project.
Service Layer Project: ContactService, etc. Each has the UnitOfWork
injected into them. References "Data Access Layer" and "Entities" project.
GUI Project: with your UI. References "Entities" and "Service Layer" project.
I think ServiceUnit is an unnecessary abstraction, and services can deal with UnitOfWork directly (unless I'm missing something).
By the way, I wouldn't recommend exposing IQueryable from your repositories (as someone suggested to me on another question). Once you expose it, the query is executed outside your repository and so you loose control over its execution (exception handling, etc.). If you search a bit you'll see there's some controversy over this.
Hi I am using Unity to manage my service layers, which in turn speak to UnitOfWork which manages all the repositories.
Some of my services call other services, my question is how can i pass the same UnitOfWork between service layers?
In my case all controller actions are initiated from a GUI on each button action or event on a timer, this is why I have a factory to create UnitOfWork on demand, but it is causing issues as i dont know how to pass this UnitOfWork between services.
Especially difficult is knowing how to get this specific UnitOfWork instance injected into the service constructor. Please note that some of the services may be long running (10 minutes or so on a background thread), i don't know if that has any impact on the design or not.
Currently the service that is called from the other service is then creating its own UnitOfWork which is causing issues for both transactional design, and Entity framework entity tracking.
Suggestions very welcome!
class OtherService : IOtherService
{
public OtherService(IUnitOfWorkFactory unitOfworkFactory,
ISettingsService settingsService)
{
UnitOfWorkFactory = unitOfworkFactory;
SettingsService = settingsService;
}
IUnitOfWorkFactory UnitOfWorkFactory;
ISettingsService SettingsService;
function SomeSeviceCall()
{
// Perhaps one way is to use a factory to instantiate a
// SettingService, and pass in the UnitOfWork here?
// Ideally it would be nice for Unity to handle all of
// the details regardless of a service being called from
// another service or called directly from a controller
// ISettingsService settingsService =
// UnityContainer.Resolve<ISettingService>();
using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
{
var companies = uow.CompaniesRepository.GetAll();
foreach(Company company in companies)
{
settingsService.SaveSettings(company, "value");
company.Processed = DateTime.UtcNow();
}
uow.Save();
}
}
}
class SettingsService : ISettingsService
{
public SettingsService(IUnitOfWorkFactory unitOfworkFactory)
{
UnitOfWorkFactory = unitOfworkFactory;
}
IUnitOfWorkFactory UnitOfWorkFactory;
// ISettingsService.SaveSettings code in another module...
function void ISettingsService.SaveSettings(Company company,
string value)
{
// this is causing an issue as it essentially creates a
// sub-transaction with the new UnitOfWork creating a new
// Entiy Framework context
using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
{
Setting setting = new Setting();
setting.CompanyID = company.CompanyID;
setting.SettingValue = value;
uow.Insert(setting);
uow.Save();
}
}
}
Hi I've been battling with this problem this is what I've come up with...
public class UnitOfWorkFactory
{
private static readonly Hashtable _threads = new Hashtable();
private const string HTTPCONTEXTKEY =
"AboutDbContext.UnitOfWorkFactory";
public static IUnitOfWork Create()
{
IUnitOfWork unitOfWork = GetUnitOfWork();
if (unitOfWork == null || unitOfWork.IsDisposed)
{
unitOfWork = new UnitOfWork();
SaveUnitOfWork(unitOfWork);
}
return unitOfWork;
}
public static IUnitOfWork GetUnitOfWork()
{
if (HttpContext.Current != null)
{
if (HttpContext.Current.Items.Contains(HTTPCONTEXTKEY))
{
return (IUnitOfWork)HttpContext
.Current.Items[HTTPCONTEXTKEY];
}
return null;
}
var thread = Thread.CurrentThread;
if (string.IsNullOrEmpty(thread.Name))
{
thread.Name = Guid.NewGuid().ToString();
return null;
}
lock (_threads.SyncRoot)
{
return (IUnitOfWork)_threads[Thread.CurrentThread.Name];
}
}
private static void SaveUnitOfWork(IUnitOfWork unitOfWork)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items[HTTPCONTEXTKEY] = unitOfWork;
}
else
{
lock (_threads.SyncRoot)
{
_threads[Thread.CurrentThread.Name] = unitOfWork;
}
}
}
public static void DisposeUnitOfWork(IUnitOfWork unitOfWork)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items.Remove(HTTPCONTEXTKEY);
}
else
{
lock (_threads.SyncRoot)
{
_threads.Remove(Thread.CurrentThread.Name);
}
}
}
}
public interface IUnitOfWork : IDisposable
{
void Commit();
bool IsDisposed { get; }
}
public class UnitOfWork : MyContext
{
}
public abstract class Repository<T>
: IRepository<T>, IDisposable where T : class
{
private UnitOfWork _context;
private UnitOfWork Context
{
get
{
if (_context == null || _context.IsDisposed)
return _context = GetCurrentUnitOfWork<UnitOfWork>();
return _context;
}
}
public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>()
where TUnitOfWork : IUnitOfWork
{
return (TUnitOfWork)UnitOfWorkFactory.GetUnitOfWork();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Where(predicate).ToList();
}
public bool Exists(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Any(predicate);
}
public T First(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Where(predicate).FirstOrDefault();
}
public IEnumerable<T> GetAll()
{
return Context.Set<T>().ToList();
}
public IEnumerable<T> GetAllOrderBy(Func<T, object> keySelector)
{
return Context.Set<T>().OrderBy(keySelector).ToList();
}
public IEnumerable<T> GetAllOrderByDescending(Func<T, object> keySelector)
{
return Context.Set<T>().OrderByDescending(keySelector).ToList();
}
public void Commit()
{
Context.SaveChanges();
}
public void Add(T entity)
{
Context.Set<T>().Add(entity);
}
public void Update(T entity)
{
Context.Entry(entity).State = EntityState.Modified;
}
public void Delete(T entity)
{
Context.Set<T>().Remove(entity);
}
public void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
GC.SuppressFinalize(this);
}
}
public class MyContext : DbContext, IUnitOfWork
{
public DbSet<Car> Cars { get; set; }
public void Commit()
{
SaveChanges();
}
protected override void Dispose(bool disposing)
{
IsDisposed = true;
UnitOfWorkFactory.DisposeUnitOfWork(this);
base.Dispose(disposing);
}
public bool IsDisposed { get; private set; }
}
Then I can do:
using (var unitOfWork = UnitOfWorkFactory.Create())
{
_carRepository.Add(new Car
{
Make = "Porshe", Name = "Boxter"
});
_carRepository.Commit();
}
You could use some kind of "current" unit of work which is tied to current thread and explicitly resolved in service code. You need class to hold thread static instance of UoW to achieve this. However, this is not very good solution.
You be the judge...
I think you are double doing it.
Point 1:
http://www.britannica.com/topic/Occams-razor
Point 2:
From the F2 object browser description of EF main object, the DBContext...
public class DbContext
Member of System.Data.Entity
Summary:
A DbContext instance represents a combination of the Unit Of Work and Repository patterns such that it can be used to query from a database and group together changes that will then be written back to the store as a unit.