链接到实体-三层架构
本文关键字:三层 实体 链接 | 更新日期: 2023-09-27 18:01:39
在过去的几个月里,我学到了很多关于链接到实体和带有DAO/DAL/Repository的三层体系结构的知识。现在有几件事一直困扰着我。我有三个问题,你将在下面看到。
有很多方法可以使存储库工作,但是什么方法是使存储库在性能方面工作的"最佳"方法呢?
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();
}
}
2) 使用"Using"
public class Repository : IRepository
{
public IList<Entity> GetEntities()
{
using (Datacontext context = new Datacontext())
{
return (from e in context.Entity
select e).ToList();
}
}
}
3) 另一种方式(请注释)
我把你的建议放在这里,让别人评论
似乎有些人认为存储库应该向业务层返回一个IQueryable,而另一些人则认为最好返回一个illist。你对此有何看法?
上面第一个问题中的代码示例指向存储库,但是在业务层实现存储库的最佳方法是什么(在构造函数中初始化,使用"Using"??)
我认为都可以。最主要的是,你应该让你的对象上下文相当短的寿命(IMHO)。因此,我认为你有两个选择:-
-
在单个方法调用中创建/销毁上下文,例如第二个示例中的using语句。
-
在创建/销毁存储库时创建/销毁上下文——在这种情况下,您的存储库应该实现IDisposable并将其本身包装在using语句中,并且应该是短寿命的。这种方法的好处是,您的存储库方法只需执行查询,而不会使用(new ObjectContext())污染方法;另一方面,责任转移到客户端来处理存储库。使用这种机制意味着您还可以在IQueryable<>中组合查询(前提是在处置存储库之前执行查询)。例如:
公共类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...
}
}
我认为这取决于你的需要…
如果您的存储库仅用于获取数据,那么我可能会使用Using技术,但说实话,您何时需要仅用于获取数据的存储库。你也会想要添加和更新,所以我肯定会去一个全局的数据上下文。这样做的好处是,您可以更新实体模型,然后保存更改。如果对每个调用使用不同的数据上下文,则无法持久化更改。
示例存储库应该是…
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,只在你真正需要使用列表
我更喜欢using模式,因为它允许代码更干净和简单,因为我们知道db上下文的范围,并且可以清楚地知道它何时被处理,这在构造函数的情况下很难说。
另外,我不认为你可以在"使用"的情况下返回IQueryable作为db上下文将被处置一旦使用块退出,然后你不能在你的业务层使用返回的IQueryable
对于我自己,我总是返回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
如果您希望能够链接您的方法,以便进行最准确的查询,请使用第一种情况。如:
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);
}
}