5

在过去的几个月里,我学到了很多关于 Linq-To-Entities 和带有 DAO/DAL/Repository 的 3 层架构的知识。现在我脑子里有一些事情一直困扰着我。我有这三个问题,您将在下面看到。

有很多方法可以使存储库工作,但是使存储库以性能方式工作的“方法”是什么。

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)使用“使用”

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中实现repository的最佳方法是什么(在构造函数中初始化,使用“Using”??)

4

5 回答 5

2

我认为要么工作。主要的是你应该让你的对象上下文相当短暂(恕我直言)。因此,我认为您有两个选择:-

  1. 在单个方法调用中创建/销毁上下文,例如根据您的第二个示例的 using 语句。

  2. 在您创建/销毁存储库时创建/销毁上下文 - 在这种情况下,您的存储库应该同时实现 IDisposable 并且本身被包装在 using 语句中,并且应该是短暂的。这种方法的好处是您的存储库方法只是进行查询,没有 using (new ObjectContext()) 污染方法;另一方面是 reposibility 传递给客户端来处理存储库。使用此机制意味着您还可以在 IQueryable<> 中编写查询(前提是您在处理存储库之前执行查询)。例如:

公共类存储库: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...
    }
}
于 2011-07-11T13:04:40.853 回答
1

我认为这取决于您的需求...

如果您的存储库仅用于获取数据,那么我可能会使用 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 并且仅在您确实需要使用列表时才调用 ToList

于 2011-07-11T12:06:55.670 回答
0

我更喜欢 using 模式,因为它可以让代码更简洁,因为我们知道 db 上下文的范围,并且可以清楚地说明它何时被处理,这在构造函数的情况下很难说。

此外,我认为您不能在“使用”的情况下返回 IQueryable,因为一旦使用块退出,数据库上下文将被释放,然后您无法在业务层中使用返回的 IQueryable。

于 2011-07-11T11:39:17.643 回答
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);
     }
}
于 2011-07-11T12:18:44.690 回答
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 更新答案

于 2011-07-11T12:32:17.503 回答