问题
In my LabelService I'm trying to join records from the OrderLineRepository with the LabelRepository. When I do this I get this error:
The specified LINQ expression contains references to queries that are associated with different contexts.
What would be the best solution for this problem? Any suggestions would be appreciated.
Here is the code for my two repositories:
public class LabelRepository : ILabelRepository
{
private OrderContext _context;
public LabelRepository(string connectionName)
{
_context = new OrderContext(connectionName);
}
public LabelRepository()
{
_context = new OrderContext();
}
public LabelRepository(OrderContext context)
{
_context = context;
}
}
public class OrderLineRepository : IOrderLineRepository
{
private OrderContext _context;
public OrderLineRepository(string connectionName)
{
_context = new OrderContext(connectionName);
}
public OrderLineRepository()
{
_context = new OrderContext();
}
public OrderLineRepository(OrderContext context)
{
_context = context;
}
}
And here is parts of the code in my LabelService:
public class LabelService : ILabelService
{
private readonly ILabelRepository _labelRepository;
private readonly IOrderLineRepository _orderLineRepository;
public LabelService(ILabelRepository labelRepository, IOrderLineRepository orderLineRepository)
{
_labelRepository = labelRepository;
_orderLineRepository = orderLineRepository;
}
public List<Label> GetLabelsOrderedByCustomerId(string customerId)
{
var labels = (from ol in _orderLineRepository.GetAll()
join l in _labelRepository.GetAll() on new {ol.QualityId, ol.CustomerId, ol.SerialNumber} equals
new {l.QualityId, l.CustomerId, l.SerialNumber}
where ol.OrderCustomer == customerId
select l).Distinct().ToList();
return labels;
}
}
Unity is used for dependency injection:
public class Resolver : IDependencyResolver
{
public object GetService(Type serviceType)
{
if (serviceType == typeof (LabelsController)) {
return new LabelsController(
new LabelService(new LabelRepository(), new OrderLineRepository()),
new OrderLineService(new OrderLineRepository())
);
}
return null;
}
}
回答1:
When I need to share context between repositories I tend to introduce an overloaded constructor which lets me pass in a context. It's best to wrap your context up in a nice interface though e.g.
public partial OrderContext : DbContext, IContext
{
...
}
public class OrderLineRepository : IOrderLineRepository
{
public OrderLineRepository(string connectionString)
: this(new OrderContext(connectionName))
{
}
public OrderLineRepository(IContext context)
{
this.Context = (OrderContext)context;
}
public IContext Context { get; private set; }
}
Then in your resolver you could do
public object GetService(Type serviceType)
{
if (serviceType == typeof (LabelsController)) {
var labelRepo = new LabelRepository();
var orderRepo = new OrderLineRepository(labelRepo.Context);
return new LabelsController(
new LabelService(labelRepo, orderRepo),
new OrderLineService(orderRepo)
);
}
return null;
}
Alternatively, another approach I have used in the past is to have a UnitOfWork
type class which exposes a context e.g.
public interface IUnitOfWork : IDisposable
{
public IContext Context { get; }
}
public class UnitOfWork : IUnitOfWork
{
public UnitOfWork(string connectionString)
{
this.Context = new OrderContext(connectionString);
}
public IContext Context { get; private set; }
public void Dispose()
{
if (Context != null)
Context.Dispose();
}
}
In your scenario, I would update my repositories to have a read/write Context
property which would allow you to swap them out in your services
public List<Label> GetLabelsOrderedByCustomerId(string customerId)
{
using (var uow = new UnitOfWork(connectionString))
{
_labelRepository.Context = uow.Context;
_orderLineRepository.Context = uow.Context;
var labels = (from ol in _orderLineRepository.GetAll()
join l in _labelRepository.GetAll() on new {ol.QualityId, ol.CustomerId, ol.SerialNumber} equals
new {l.QualityId, l.CustomerId, l.SerialNumber}
where ol.OrderCustomer == customerId
select l).Distinct().ToList();
return labels;
}
}
回答2:
The best solution would be to stop using repositories altogether. DbContext
hides the database well enough, and repositories don't really help you with unit tests (you spend a lot of time creating mock versions, while what you really should be doing is create a database instance for unit tests and use EF).
Aside from that, you should pass the same context to all your repositories, that way you can share objects between them very easily.
来源:https://stackoverflow.com/questions/21696969/how-should-i-setup-my-repositories-to-use-the-same-context