Question

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;
}
}
Was it helpful?

Solution

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;   
    }
}

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top