Entity Framework,仓储模式

3
我正在尝试使用Entity Framework - Repository模式。(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);
}

我尝试将上下文定义为静态的,并与IT技术相关联。

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

我搜索了很多实体框架-仓储模式的资料,但大部分都非常复杂。因此,我希望像上面那样简化它。

请给我建议~

谢谢!

[编辑]

我尝试了这个,

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个回答

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;
  }

更新:
如果您尝试上述仓库测试,您需要进行一些重构。它不适用于您的类当前状态。这将是您需要发布的另一个问题。上面的代码片段只是您查询可能看起来像的示例。依赖注入(DI),如@Florim Maxhuni所建议的,确实是正确的路线...只是取决于您的要求和时间限制。如果您遇到DbContext的问题,则应发布一个新主题。


啊哈!这个错误困扰了我的问题的目的 :( 你觉得仓库代码(带有静态变量)可以吗?我能在我的项目中使用它吗? - Expert wanna be
不必将上下文传递给每个存储库,您可以使用受保护的静态方法,但我不确定在处理和重新实例化方面的影响。如果使用从最内部的“using”开始的语句,则将调用所有Dispose方法。 - IAbstract
2
你应该使用依赖注入(DI)(这样你就可以每个请求创建一个DBContext),在你的情况下,这样你就不会为每个Repository创建一个DBContext(这会减慢你的网页速度)。 - Florim Maxhuni

1

每个存储库都创建自己的上下文实现是错误的。相反,必须将上下文注入到存储库中,构造函数注入在这里非常有效。

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


DB上下文应该在仓储之间共享。在ASP .NET应用程序中通常的做法是每个HTTP请求有一个上下文。需要创建一个实现IHttpModule接口的http模块类,在请求开始时初始化上下文并将其存储在HttpContext.Items中。在请求结束时,您应该释放上下文。IoC容器还可以使用HTTP请求生命周期来初始化对象。 - Dmitry S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接