Linq to Entities - 3层架构

时间:2011-07-11 11:27:01

标签: c# linq-to-entities dao 3-tier

在过去的几个月里,我学到了很多关于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”??)

5 个答案:

答案 0 :(得分:2)

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

  1. 在单个方法调用中创建/销毁上下文,例如根据你的第二个例子,使用声明。

  2. 在创建/销毁存储库时创建/销毁上下文 - 在这种情况下,您的存储库应该实现IDisposable并且本身应该包含在using语句中,并且应该是短暂的。这种方法的好处是你的存储库方法只是简单地进行查询,没有使用(new ObjectContext())污染方法;另一方面,可转移性传递到客户端以处置存储库。使用此机制意味着您还可以在IQueryable&lt;&gt;中撰写查询。 (前提是您在处置存储库之前执行查询)。例如:

  3. 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

更新答案