实体框架,存储库模式

时间:2012-07-14 15:00:32

标签: c# asp.net-mvc-3 entity-framework-4 repository-pattern

我正在尝试使用Entity Framework - Repository Pattern。 (Asp.net C#,EF4)

我为每个数据库表创建了存储库。但是当我连接表时,会出现一个错误,说

“指定的LINQ表达式包含对与不同上下文关联的查询的引用。”

为了避免出现错误信息,我将所有内容放入一个类中,如下所示:

public class WebOrderRepository
{
    private DbEntities context = new DbEntities(); //Web.config <add name="DBEntities" connectionString=" ...

    public IQueryable<WEBORDERHD> WebOrderHds
    {
        get { return context.WEBORDERHDs; }
    }

    public IQueryable<WEBORDERLN> WebOrderLns
    {
        get { return context.WEBORDERLNs; }
    }
}

你能查看我的代码吗?

这是我的存储库类

public class Repository : IDisposable
{
    protected ShkAdsEntities context;
    private bool _disposed;

    public Repository()
    {
        context = new ShkAdsEntities();
    }

    public void Dispose() //If define this class as Static then, 'Dispose': cannot declare instance members in a static class

    {
        DisposeObject(true);
        GC.SuppressFinalize(this);
    }

    ~Repository()
    {
        DisposeObject(false);
    }

    private void DisposeObject(bool disposing)
    {
        if (_disposed)
        {
        return;
        }

        if(disposing){
        if (context != null)
        {
            context.Dispose();
        }
        _disposed = true;
        }
    }
}

public class WebOrderHdRepository : Repository
{
    public IQueryable<WEBORDERHD> WebOrderHds
    {
        get { return context.WEBORDERHDs; }
    }

    public void Create(WEBORDERHD obj)
    {
    }

    public void Delete(WEBORDERHD ojb)
    {
    }

    public void SubmitChanges()
    {
        context.SaveChanges();
    }
}

public class WebOrderLnRepository : Repository
{
    public IQueryable<WEBORDERLN> WebOrderLns
    {
        get { return context.WEBORDERLNs; }
    }

    public void Create(WEBORDERLN obj)
    {
    }

    public void Delete(WEBORDERLN ojb)
    {
    }

    public void SubmitChanges()
    {
        context.SaveChanges();
    }
}

这是测试控制器,

[HttpGet]
public ActionResult repositoryTest()
{
    WebOrderHdRepository webOrderHdRepository = new WebOrderHdRepository();
    WebOrderLnRepository webOrderLnRepository = new WebOrderLnRepository();

    var result = (from x in webOrderHdRepository.WebOrderHds
          join u in webOrderLnRepository.WebOrderLns on x.OrderNo equals u.OrderNo
          select new {x.OrderNo}).SingleOrDefault();

    return Content(result.OrderNo);
}

我尝试将上下文定义为静态,

protected static ShkAdsEntities context = null;
public Repository()
{
    if (context == null)
    {
    context = new ShkAdsEntities();
    }
}

然后,发生另一个错误,

Sequence contains more than one element
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Sequence contains more than one element

Source Error:


Line 116:        {
Line 117:            WebOrderHdRepository webOrderHdRepository = new WebOrderHdRepository();
Line 118:            WebOrderLnRepository webOrderLnRepository = new WebOrderLnRepository();  <== ERROR POINT
Line 119:
Line 120:            var result = (from x in webOrderHdRepository.WebOrderHds

我搜索了许多Entity Framework-Repository模式。但大多数事情都非常复杂。所以我想像上面那样简单。

请指教我〜

谢谢!

[编辑]

我试着这个,

using(WebOrderHdRepository webOrderHdRepository = new WebOrderHdRepository())
using (WebOrderLnRepository webOrderLnRepository = new WebOrderLnRepository())
{
.
.

但发生错误,

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Source Error:


Line 114:        {
Line 115:            using(WebOrderHdRepository webOrderHdRepository = new WebOrderHdRepository())
Line 116:            using (WebOrderLnRepository webOrderLnRepository = new WebOrderLnRepository())
Line 117:            {
Line 118:

我认为它试图处理两次,但我不知道如何修复代码......

任何人都知道,请指教我〜

由于

2 个答案:

答案 0 :(得分:3)

您将能够将异常追溯到此声明:

var result = (from x in webOrderHdRepository.WebOrderHds
      join u in webOrderLnRepository.WebOrderLns on x.OrderNo equals u.OrderNo
      select new {x.OrderNo}).SingleOrDefault();

错误发生在SingleOrDefault中 - 您的收藏集有多个结果。查看MSDN文档以确定是否应使用FirstOrDefault

具体涉及SingleOrDefault行为,MSDN解释(强调添加):

  

返回序列的唯一元素,如果是,则返回默认值   序列是空的; 如果有更多内容,此方法会抛出异常   比序列中的一个元素

关于您的DbContext,您应该能够拥有单独的存储库,只需确保每个存储库使用相同的上下文对象。我猜想(没有看到原始实现)每个存储库都实例化了它自己的上下文对象。我没有看到您当前实现的任何特定问题,尽管有些可能会提示类似以下内容(未经测试的):

  public ActionResult repositoryTest() {
     ActionResult actionRes = default(ActionResult);

     using (ShkAdsEntities context = new ShkAdsEntities())
     using (WebOrderHdRepository webOrderHdRepository = new WebOrderHdRepository(context))
     using (WebOrderLnRepository webOrderLnRepository = new WebOrderLnRepository(context)) {

        var result = (from x in webOrderHdRepository.WebOrderHds
                      join u in webOrderLnRepository.WebOrderLns on x.OrderNo equals u.OrderNo
                      select new { x.OrderNo }).SingleOrDefault();

        actionRes = Content(result.OrderNo);
     }

     return actionRes;
  }

<强>更新
如果您尝试上面演示的存储库测试,则需要进行一些重构。它不适用于您班级的当前状态。这将是您需要发布的另一个问题。上面的代码段只是您的查询可能的示例。正如@ Florim Maxhuni所暗示的那样,依赖注入(DI)真的是要走的路......根据你的要求和时间限制。如果你的DbContext有问题,那将是一个不同的问题,应该发布在一个新的线程中。 :)

答案 1 :(得分:1)

每个存储库创建自己的上下文的错误都是错误的。相反,必须将上下文注入到存储库中,构造函数注入在这里工作得很好。

通过这种方式,您可以完全控制上下文并在存储库之间共享它。例如,在Web应用程序中,您可以拥有一个生命周期为单个请求的上下文。