I do not find correct way in my MVC app how to bind repositories and all EF related data. The example below create new DbContext for every IRepository and this give me error
An entity object cannot be referenced by multiple instances of
IEntityChangeTracker
This error appears because my Entities in different context. For example the code(it is in Entity) will give error
var user = new User();
_userRepository.Insert(user)
var order = new Order();
order.User = user;
_orderRepository.Insert(order)
_unitOfWork.Commit();
If I change
kernel.Bind(typeof(DbContext)).ToMethod(context => new DbContext(connectionString));
to
kernel.Bind(typeof(DbContext)).ToMethod(context => new DbContext(connectionString)).InRequestScope();
I get error
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
if i use ServiceRepository in separated thread.
Maybe someone know solution?
var connectionString = ConfigurationManager.ConnectionStrings["Entities"].ConnectionString;
kernel.Bind(typeof(DbContext)).ToMethod(context => new DbContext(connectionString));
kernel.Bind<IObjectSetFactory>().ToMethod(c => kernel.Get<DbContextAdapter>());
kernel.Bind<IObjectContext>().ToMethod(c => kernel.Get<DbContextAdapter>());
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork));
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
public interface IServiceRepository
{
UserDetail GetUser(int id);
User GetUser(string email);
User GetUser(string email, string password);
OrderDetail GetOrder(string id);
IEnumerable<OrderDetail> GetOrders(int userId);
IEnumerable<Product> GetProducts();
UserDetail GetParentUser(string partialEmail);
IEnumerable<UserDetail> GetChildUsers(int parentId);
IEnumerable<Statistic> GetStatisticForCurrentMonth(string ip);
void InsertStatistic(QueueItem queueItem);
void InsertStatistic();
void Commit();
void AddUser(User model);
User AddUser(string firstName, string lastName, string email, string password, string country, int? parentId = null, DateTime? dateStamp = null);
void AddOrder(Order order);
void DeleteUser(int id);
void DeleteUser(string email);
bool OrderManager(PaymentProcessorOrder order, out User newUser, out Order newOrder);
User AuthenticatedUser();
string AuthenticatedUserEmail();
bool ValidateUser(string email, string password);
string GetPassword(string email);
}
public class ServiceRepository : IServiceRepository
{
private readonly IRepository<User> _userRepository;
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<UserDetail> _userDetailRepository;
private readonly IRepository<Statistic> _statisticRepository;
private readonly IRepository<Product> _productRepository;
private readonly IRepository<OrderDetail> _orderDetailRepository;
private readonly IUnitOfWork _unitOfWork;
private static readonly object Locker = new object();
public ServiceRepository(IRepository<User> userRepository, IRepository<Statistic> statisticRepository, IRepository<UserDetail> userDetailRepository, IRepository<Order> orderRepository, IUnitOfWork unitOfWork, IRepository<OrderDetail> orderDetailRepository, IRepository<Product> productRepository)
{
_unitOfWork = unitOfWork;
_userRepository = userRepository;
_statisticRepository = statisticRepository;
_userDetailRepository = userDetailRepository;
_orderRepository = orderRepository;
_orderDetailRepository = orderDetailRepository;
_productRepository = productRepository;
}
//Skip code
}
You shouldn’t use threads in an ASP.NET application because it gives you many problems. E.g. when IIS recycles you App Pool or suspends the application your threads will be terminated leaving your application in an inconsistent state. Or an uncatched exception in your thread can tear down your whole application.
Usually, you should implement async things in a separate service application so that IIS just has to send some message which will be processed asyncronously be this service. This will also solve your problem as you can use an other DbContext for each message.
If you really want to use background threads then you have to use different bindings for the DbContext for your requests and threads. E.g.
But this means you can’t pass entities from the request DbContext to the background thread context.