在过去的几个月里,我学到了很多关于Linq-To-Entities和带有DAO / DAL / Repository的3层架构。现在我脑子里有一些让我烦恼的事情。我将在下面提到这三个问题。
有很多方法可以使存储库工作,但是以何种方式使存储库以性能的方式工作。
1)在构造函数中初始化datacontext
public class Repository : IRepository
{
private Datacontext context;
public Repository()
{
context = new Datacontext();
}
public IList<Entity> GetEntities()
{
return (from e in context.Entity
select e).ToList();
}
}
2)使用“使用”
public class Repository : IRepository
{
public IList<Entity> GetEntities()
{
using (Datacontext context = new Datacontext())
{
return (from e in context.Entity
select e).ToList();
}
}
}
3)以另一种方式(请发表评论)
我会在此提出您的建议供其他人发表评论
似乎有些人说存储库应该将IQueryable返回给业务层,而其他人则认为返回IList更好。你对此有何看法?
第一个问题中的上述代码示例指向Repository,但是在businesslayer中实现存储库的最佳途径是什么(在构造函数中初始化,使用“Using”??)
答案 0 :(得分:2)
我认为是有效的。主要的是你应该让你的对象上下文相当短暂(恕我直言)。因此,我认为你有两个选择: -
在单个方法调用中创建/销毁上下文,例如根据你的第二个例子,使用声明。
在创建/销毁存储库时创建/销毁上下文 - 在这种情况下,您的存储库应该实现IDisposable并且本身应该包含在using语句中,并且应该是短暂的。这种方法的好处是你的存储库方法只是简单地进行查询,没有使用(new ObjectContext())污染方法;另一方面,可转移性传递到客户端以处置存储库。使用此机制意味着您还可以在IQueryable&lt;&gt;中撰写查询。 (前提是您在处置存储库之前执行查询)。例如:
public class Repository:IDisposable { DataHubContext context = new DataHubContext();
public IQueryable<Payment> GetPayments()
{
return context.Payments;
}
public void Dispose()
{
context.Dispose();
}
}
格式化在SO中有点搞笑 - 抱歉....然后在你的调用代码中: -
public class ClientCode
{
public void DisplayPaymentsOnScreen()
{
Payment[] payments;
using (var repository = new Repository())
{
payments = repository.GetPayments().Where(p => p.Amount > 100).ToArray();
}
// Do stuff with the data here...
}
}
答案 1 :(得分:1)
我认为这取决于您的需求......
如果您的存储库仅用于获取数据,那么我可能会使用“使用”技术,但说实话,您何时需要存储库来获取数据。您还需要添加和更新,因此我肯定会选择全局数据上下文。这样做的好处是,您可以更新实体模型,然后保存更改。如果您为每个呼叫使用不同的数据上下文,则无法保留更改。
示例存储库类似于......
public class Repository : IRepository
{
private Datacontext context;
public Repository()
{
context = new Datacontext();
}
public IList<Entity> GetEntities()
{
return (from e in context.Entity
select e).ToList();
}
public void Save()
{
context.SubmitChanges();
}
}
...然后您可以进行许多数据更改并一次性提交到数据库。要考虑的另一点是,在你的GetEntities中,你可以调用ToList()。当你调用它时,你实际上是在那里执行数据库查询。如果您打算对结果进行进一步的逻辑处理,您可能希望返回IQueryable而只在您确实需要使用列表时调用ToList
答案 2 :(得分:0)
我更喜欢使用模式,因为我们知道db上下文的范围,并且可以说明何时这样处理,这很容易让代码变得更干净和简单,这在构造函数的情况下很难说。
另外,我不认为你可以在“使用”的情况下返回IQueryable,因为在使用块退出后将立即处理db上下文,然后你不能在业务层中使用返回的IQueryable。
答案 3 :(得分:0)
如果您希望能够链接方法以获得最准确的查询,请使用第一种情况。例如:
public class Repository : IRepository
{
private Datacontext context;
public Repository()
{
context = new Datacontext();
}
public IQueryabale<Entity> SelectAllEntities()
{
return context.Entity.Where(e=>! e.IsObsolote);
}
public IQueryable<Entity> SelectAllEntityRelatedToAnotherEntity(Entity otherEntity)
{
return this.SelectAllEntities().Where(e=>e.RelatedEntityId == otherEntity.Id);
}
}
修改
You can use it in collaboration with your business layer like this:
public class EntityManager()
{
public IQueryable<Entities> FindAllApprovedEntities(Entity other)
{
return new Repository().SelectAllEntityRelatedToAnotherEntity(other).Where(e=>e.Approved);
}
}
答案 4 :(得分:0)
对我来说,我总是会回来IQueryable<T>
public IQueryable<Entity> GetEntities()
{
return from e in context.Entity select e;
}
你必须阅读延迟执行http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx我使用它所以我可以在业务逻辑或UI中查询实体的确切部分而不是整个实体(它像select *
)
我更喜欢在构造函数
中初始化上下文public class Repository : IRepository
{
private Datacontext context;
public Repository()
{
context = new Datacontext();
}
public IQueryable<Entity> GetEntities()
{
return from e in context.Entity select e;
}
public int Save()
{
// Return the number of the affected rows to determine in your code whether your query executed or not
return context.SubmitChanges();
}
}
注意:此外,在设计EF存储库时,请确保所有存储库中都有上下文的一个实例,以避免在更新和删除期间出现错误。
我有一个我在公司制作的通用存储库,我计划很快发布它,它允许你轻松地进行CRUD操作,你可以用很少的代码扩展它。完成后,我将使用URL
更新答案