in my one application i am getting this error. Repository code
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
readonly IDbContext _context;
IDbSet<TEntity> DbSet;
public BaseRepository(IDbContext context)
{
_context = context;
DbSet = context.Set<TEntity>();
}
#region Implementation of IRepository<TEntity>
public TEntity FindById(object id)
{
return DbSet.Find(id);
}
public void Add(TEntity entity)
{
_context.Entry(entity).State=EntityState.Added;
// DbSet.Add(entity);
}
public void Update(TEntity entity)
{
_context.Entry(entity).State = EntityState.Modified;
// DbSet.Attach(entity);
}
public void Delete(TEntity entity)
{
if (entity == null) return;
_context.Entry(entity).State = EntityState.Deleted;
DbSet.Remove(entity);
}
public void Delete(object id)
{
Delete(FindById(id));
}
public IQueryable<TEntity> GetAll()
{
return DbSet;
}
public IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate);
}
#endregion
}
UnitOfWork Code
public class UnitOfWork : IUnitOfWork
{
private readonly IDbContext _context;
private bool _disposed;
private Hashtable _repositories;
public UnitOfWork(IDbContext dbContext)
{
_context = dbContext;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Save()
{
_context.SaveChanges();
}
public virtual void Dispose(bool disposing)
{
if (!_disposed)
if (disposing)
_context.Dispose();
_disposed = true;
}
public IRepository<T> Repository<T>() where T : class
{
if (_repositories == null)
_repositories = new Hashtable();
var type = typeof(T).Name;
if (!_repositories.ContainsKey(type))
{
var repositoryType = typeof(BaseRepository<>);
var repositoryInstance =
Activator.CreateInstance(repositoryType
.MakeGenericType(typeof(T)), _context);
_repositories.Add(type, repositoryInstance);
}
return (IRepository<T>)_repositories[type];
}
}
And my Service class
public class OrderService : IOrderService
{
private readonly ICoreUnitOfWork _unitOfWork;
private readonly IRepository<Order> _repository;
public OrderService(ICoreUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_repository = _unitOfWork.Repository<Order>();
//_orderDetailsReposiotry = _unitOfWork.Repository<OrderDetails>();
}
#region Implementation of IOrderService
public void PlaceNewOrder(Order order)
{
if (order.Detailses.Count == 0) throw new ArgumentException("Sorry! your order doesn't contains any item");
_repository.Add(order);
_unitOfWork.Save();
_unitOfWork.Dispose(true);
}
#endregion
}
Controller Code
[HttpPost]
public ViewResult OrderSummury(Cart cart, ShippingAddress address)
{
if (cart.Lines.Count == 0)
{
TempData["result"] = string.Format(" Sorry! your cart is empty");
return View(new ShippingAddress());
}
try
{
_distributer = _distributerService.GetDistributerbyEmail(User.Identity.Name);
var order = new Order();
order.OrderCreated = DateTime.Now.Date;
var refrenceArray = Guid.NewGuid().ToString().Split('-');
order.ReferenceCode += string.Format("{0}{1}", refrenceArray[1], refrenceArray[2]);
order.Status = 0;
order.ShippingAddress = address.AddressLine;
order.ShippingContactPerson = address.ContactPerson;
order.ShippingMobile = address.ShippingMobile;
order.Distributer = _distributer;
foreach (var line in cart.Lines)
{
order.AddOrderItem(new OrderDetails {Product =line.Product, Quantity = line.Quantity, UnitPrice = line.Product.Price * line.Quantity });
}
_orderService.PlaceNewOrder(order);
cart.Clear();
TempData["result"] = string.Format(" Order place with code {0} successfully", order.ReferenceCode);
}
catch (ArgumentException exception)
{
TempData["result"] = exception.Message;
}
catch (Exception e)
{
TempData["result"] = "An unknown error occurred";
LoggingFactory.GetLogger().LogError("Order registration", e);
}
return View(address);
}
My Problem
When i execute the above codes i am getting an error with message An entity object cannot be referenced by multiple instances of IEntityChangeTracker. I checked everything and i found the following findings
1.) The error caused when i am referencing product entity order.AddOrderItem(new OrderDetails {Product =line.Product
2.)In my controller Product entities are loading from session ( I am using my own custommodel binder for reading values from session and it is working well ).
Why i am getting this error ? Any suggession
On top of the generic repository, you need to use a unit of work in order to avoid the multiple context references on the entities. Basically, the unit of work should allow many repositories to work together under the same context. I do it something like this:
public class UnitOfWork : IUnitOfWork
{
private readonly MyContext _context;
public UnitOfWork()
{
_context = new MyContext();
}
public void Save()
{
_context.SaveChanges();
}
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);
}
public MyContext Context
{
get { return _context; }
}
}
Then the generic repo:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly UnitOfWork _unitOfWork;
public Repository() : this(new UnitOfWork())
{
}
public Repository(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork ?? new UnitOfWork();
}
public IList<TEntity> GetAll()
{
try
{
return _unitOfWork.context.Set<TEntity>().ToList();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return Enumerable.Empty;
}
}
public TEntity GetById(int id)
{
try
{
return _unitOfWork.context.Set<TEntity>().Find(id);
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return null;
}
}
public TEntity Get(TEntity entity)
{
try
{
return _unitOfWork.context.Set<TEntity>().Find(entity);
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return null;
}
}
public bool Add(TEntity entity)
{
try
{
_unitOfWork.context.Set<TEntity>().Add(entity);
_unitOfWork.Save();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
public bool Update(TEntity entity)
{
try
{
_unitOfWork.context.Set<TEntity>().Attach(entity);
_unitOfWork.context.Entry(entity).State = EntityState.Modified;
_unitOfWork.Save();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
public bool Delete(TEntity entity)
{
try
{
var entityToRemove = Get(entity);
_unitOfWork.context.Set<TEntity>().Remove(entityToRemove);
_unitOfWork.Save();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
public bool DeleteById(int id)
{
try
{
var entityToRemove = GetById(id);
_unitOfWork.context.Set<TEntity>().Remove(entityToRemove);
_unitOfWork.Save();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
}
When you want to use multiple repositories within the same context, you just instantiate the respective repositories with the same unit of work:
UnitOfWork uo = new UnitOfWork();
FooRepository example1 = new FooRepository(uo);
BarRepository example2 = new BarRepository(uo);
// do operations...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.