简体   繁体   English

实体框架,存储库模式

[英]Entity Framework, Repository Pattern

I'm trying to use Entity Framework - Repository Pattern. 我正在尝试使用Entity Framework - Repository Pattern。 (Asp.net C#, EF4) (Asp.net C#,EF4)

I make repositories for each DB tables. 我为每个数据库表创建了存储库。 but when I join tables, an error occur that say 但是当我连接表时,会出现错误

"The specified LINQ expression contains references to queries that are associated with different contexts." “指定的LINQ表达式包含对与不同上下文关联的查询的引用。”

To avoid the error message,I put all into one class,like this : 为了避免错误消息,我将all放入一个类中,如下所示:

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

Could you review my code please? 你能查看一下我的代码吗?

This is my repository class, 这是我的存储库类,

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

and this is the controller for test, 这是测试的控制器,

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

and I try to define context as static, 我尝试将上下文定义为静态,

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

then, the other error occur, 然后,发生另一个错误,

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

I search many for Entity Framework-Repository pattern. 我搜索了许多Entity Framework-Repository模式。 but most of things are very complicated. 但大多数事情都非常复杂。 so I want to make it simple as above. 所以我想像上面那样简单。

Please advice me~ 请指教我〜

Thanks! 谢谢!

[EDIT] [编辑]

I try to this, 我试着这个,

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

but an error occur, 但是会发生错误,

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:

I think it try to dispose twice time, but I don't know how to fix the code... 我认为它试图处理两次,但我不知道如何修复代码......

anybody know, please advice me~ 谁知道,请指教我〜

Thanks 谢谢

You will be able to trace the exception back to this statement: 您将能够将异常追溯到此语句:

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

The fault occurs in SingleOrDefault - your collection has more than one result. 故障发生在SingleOrDefault - 您的集合有多个结果。 Review the MSDN documentation to determine if you should use FirstOrDefault instead. 查看MSDN文档以确定是否应使用FirstOrDefault

Specifically concerning SingleOrDefault behavior, MSDN explains (emphasis added): 特别是关于SingleOrDefault行为,MSDN解释(重点补充):

Returns the only element of a sequence, or a default value if the sequence is empty; 返回序列的唯一元素,如果序列为空,则返回默认值; this method throws an exception if there is more than one element in the sequence . 如果序列中有多个元素,则此方法抛出异常

Regarding your DbContext, you should be able to have separate repositories, just ensure that each repository is using the same context object. 关于您的DbContext,您应该能够拥有单独的存储库,只需确保每个存储库使用相同的上下文对象。 I would guess (without seeing the original implementation) that each repository instantiated it's own context object. 我猜想(没有看到原始实现)每个存储库都实例化了它自己的上下文对象。 I don't see any particular issues with your current implementation although some may suggest something like the following ( untested ): 我没有看到您当前实现的任何特定问题,虽然有些可能会提示如下( 未经测试 ):

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

Update: 更新:
If you do try the repository test I demonstrate above, you will need to do some refactoring. 如果您尝试上面演示的存储库测试,则需要进行一些重构。 It will not work with the current state of your classes. 它不适用于您班级的当前状态。 This would be a different question you would need to post. 这将是您需要发布的另一个问题。 The above snippet is only an example of what your query could look like. 以上片段是唯一的查询可能是什么样子的例子。 Dependency Injection (DI), as @ Florim Maxhuni suggests, is really the route to go ...simply depends on your requirements and time constraints. 正如@ Florim Maxhuni所暗示的那样,依赖注入(DI)真的是要走的路......根据你的要求和时间限制。 If you have issues with your DbContext, that would be a different question and should be posted in a new thread. 如果你的DbContext有问题,那将是一个不同的问题,应该发布在一个新的线程中。 :) :)

An impoementation where each repository creates its own context is just wrong. 每个存储库创建自己的上下文的错误都是错误的。 Instead, the context must be injected to the repository, constructor injection works great here. 相反,必须将上下文注入到存储库中,构造函数注入在这里工作得很好。

This way you have a full control of the context and of sharing it between repositories. 通过这种方式,您可以完全控制上下文并在存储库之间共享它。 For example, in a web app, you could have a context with a lifetime of a single request. 例如,在Web应用程序中,您可以拥有一个具有单个请求生命周期的上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM