我应该如何设置我的存储库以使用相同的上下文?

时间:2014-02-11 08:47:22

标签: c# linq entity-framework dbcontext

在我的LabelService中,我正在尝试将OrderLineRepository中的记录与LabelRepository连接起来。当我这样做时,我收到此错误:

  

指定的LINQ表达式包含对查询的引用   与不同的背景相关联。

这个问题的最佳解决方案是什么?任何建议将不胜感激。

以下是我的两个存储库的代码:

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

以下是我的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用于依赖注入:

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

2 个答案:

答案 0 :(得分:2)

当我需要在存储库之间共享上下文时,我倾向于引入一个重载的构造函数,它允许我传入一个上下文。最好将你的上下文包装在一个漂亮的界面中,例如。

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

然后在你的解析器中你可以做到

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

或者,我过去使用的另一种方法是使用UnitOfWork类型类来暴露上下文,例如。

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

在您的方案中,我会更新我的存储库以获得读/写Context属性,这样您就可以在服务中交换它们

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

答案 1 :(得分:-4)

最佳解决方案是完全停止使用存储库。 DbContext能够很好地隐藏数据库,而且存储库并不能帮助您进行单元测试(您花了很多时间创建模拟版本,而您真正应该做的是为单元测试创​​建数据库实例并使用EF)。

除此之外,您应该将相同的上下文传递给所有存储库,这样您就可以非常轻松地在它们之间共享对象。