C# 使用dbContext的正确方法

C# 使用dbContext的正确方法,c#,asp.net-mvc,entity-framework,asp.net-mvc-4,dbcontext,C#,Asp.net Mvc,Entity Framework,Asp.net Mvc 4,Dbcontext,摘要 这是一个方法论问题。答案应该是与所描述场景的上下文一起工作时指向圣杯的链接 我们在MVCWeb应用程序项目中遇到了与dbContext的使用相关的不同问题 在阅读了许多问答博客、文章之后。。。包括关于存储库和注入模式、Owin、实体框架、Ninject的建议,我们仍然不清楚使用dbContext的正确方法 有没有一篇文章,demo,在一个比“CRUD”操作更复杂的应用程序中使用MVVC表示层/域实体/逻辑层/数据访问层(包括身份安全处理用户和角色权限)之间的分离来实现它的“方法” 说明 以

摘要

这是一个方法论问题。答案应该是与所描述场景的上下文一起工作时指向圣杯的链接

我们在MVCWeb应用程序项目中遇到了与dbContext的使用相关的不同问题

在阅读了许多问答博客、文章之后。。。包括关于存储库和注入模式、Owin、实体框架、Ninject的建议,我们仍然不清楚使用dbContext的正确方法

有没有一篇文章,demo,在一个比“CRUD”操作更复杂的应用程序中使用MVVC表示层/域实体/逻辑层/数据访问层(包括身份安全处理用户和角色权限)之间的分离来实现它的“方法”

说明

以前,我们的方法是在需要时在每个存储库中创建dbContext对象。 很快,我们发现了类似“dbContext已释放”的错误,因为连接与存储库函数一起消失。这使得检索到的对象对应用程序中的上层“部分可用”(使用trick.ToList(),这是有限的,因为我们可以访问集合和属性,但不能稍后导航到对象子表,等等)。同样使用来自不同存储库的两个上下文,我们得到一个异常,告诉我们有两个上下文试图注册对同一对象的更改

由于交付原型的时间承诺,我们为整个应用程序创建了一个共享的静态dbContext,在需要时从任何地方(控制器、模型、逻辑、DataAccess、数据库初始化器)调用它。我们知道这是一个非常肮脏的解决方法,但它比以前的方法工作得更好

仍然存在问题:dbContext一次只能处理1个异步方法调用,并且我们可以有很多调用(例如userManager.FindByNameAsync-只有异步方法)。异常:“在上一个异步操作完成之前,在此上下文上启动了第二个操作”

当在控制器中调用某个动作时,我们考虑将创建上下文作为第一步,然后将此对象作为“中继竞争”传递到其他所有被调用的层或函数。通过这种方式,连接将从“在浏览器中单击”一直保持,直到响应加载回它。但我们不喜欢这样的想法,即每个函数都必须有一个额外的参数“context”,以便在整个操作路径的各个层中共享连接

我们确信,我们不是第一个想知道什么是使用上下文的正确方式的人

应用程序层

我们有这些(逻辑)层,不同的工作区,但相同的webapp MVC项目,自上而下:

  • 视图:HTML+Razor+JQuery+CSS。此处的代码仅限于布局,但某些HTML可能取决于角色。方法调用仅限于控制器和UTIL(如格式化)

  • 视图模型:要在控制器和视图之间交换的数据容器。类仅定义属性,以及仅与域实体(转换器)进行转换的函数

  • 控制器:从浏览器调用的操作会导致调用逻辑层中的函数。此处的身份验证限制对操作的访问或限制操作内部的访问。控制器避免使用域实体,而是使用ViewModels,以便与逻辑层通信,调用ViewModels转换函数

  • 域实体:用于逻辑层,用于按实体框架创建数据库表

  • 逻辑类:域实体具有包含所有操作的EntityLogic类。这些是核心,其中所有通用的规则都是从特定的消费者客户机抽象出来的(ViewModels是未知的)

  • 存储库:访问数据库。不确定我们是否需要这个,因为域实体已经通过实体框架映射到数据库中的对象

典型场景

  • 浏览器在产品控制器中调用操作(POST)以编辑产品。ProductViewModel用作数据的容器

  • 控制器操作仅限于一组角色。在操作内部,根据角色的不同,调用不同的逻辑函数,并将ProductViewModel转换为ProductDomainEntity并作为参数传递

  • logic EditProduct函数调用不同逻辑类中的其他函数,并使用本地化和安全性来限制或过滤。逻辑可以调用存储库来访问数据,也可以不调用存储库来使用全局上下文来访问所有数据,并将生成的域实体集合交付给逻辑

  • 根据结果,逻辑可能会也可能不会尝试导航结果的子集合。结果作为域实体(或的集合)返回给控制器操作,并且根据此结果,控制器可以调用更多逻辑,或者重定向到另一个操作,或者使用将结果转换到正确ViewModel的视图进行响应

  • 在何处、何时以及如何创建dbContext以最佳方式支持整个操作?

    更新:逻辑层中的所有类都是静态的。这些方法从控制器中调用,如下所示:

    UserLogic.GetCompanyUserRoles(user)
    
    ,或

    其中GetCompanyRoles()是在UserLogic中实现的User的扩展方法。因此,没有逻辑类的实例意味着没有构造函数来接收dbContext以在其方法中使用

    我希望静态类中的静态方法知道在何处将dbContext的实例激活到当前HttpRequest
    user.GetCompanyRoles()
    
    if(Save)
       db.SaveChanges();