【发布时间】:2015-06-30 16:36:34
【问题描述】:
我目前正在为客户构建一个大型解决方案,其中代码可重用性是关键字,因为不同类型的项目(即网站、WCF 服务、WPF 等)应该使用完全相同的业务逻辑。
现在,我的解决方案如下所示:
- 业务逻辑层(定义业务规则的所有逻辑都在这里添加)
- 接口
- 模型(ViewModel、DTO 等)
- 存储库(当前使用 Entity Framework 6。这是所有数据库事务所在的位置)
- Web 服务(WCF 服务)
- MVC 网站
关键是任何表示层(即 MVC 网站)都将使用业务逻辑层,然后使用存储库进行所需的任何数据库事务。
虽然这按我想要的方式工作,但我发现自己一直在与实体框架中的 ObjectContext 作斗争,这仅仅是因为在查询存储库中的数据时,实体不会转移到业务逻辑(这是合乎逻辑的,因为EF 延迟加载)我知道我可以使用.Include(x => x.MyOtherTable),但由于数据库相当大,这种方法很快就会变得臃肿,如果包含的表有很多记录,查询可能会相当大。
然后我创建了一个 DbContextManager 类,如下所示:
public static class DbContextManager
{
//Unique context key per request and thread
private static string Key
{
get
{
return string.Format("MyDb_{0}{1}", HttpContext.Current.GetHashCode().ToString("x"), Thread.CurrentContext.ContextID);
}
}
//Get and set request context
private static MyEntities Context
{
get { return HttpContext.Current.Items[Key] as MyEntities ; }
set { HttpContext.Current.Items[Key] = value; }
}
//Context per request
public static MyEntities Current
{
get
{
//if null, create new context
if (Context == null)
{
Context = new MyEntities ();
HttpContext.Current.Items[Key] = Context;
}
return Context;
}
}
//Dispose any created context at the end of a request - called from Global.asax
public static void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
}
}
在我的 global.asax 中,我在请求结束时处理上下文:
private void Application_EndRequest(object sender, EventArgs e)
{
DbContextManager.Dispose();
}
这很完美,我现在可以在存储库中进行初始数据库调用,然后在我的业务逻辑层中制定业务逻辑规则,这仅仅是因为 ObjectContext 为 http 请求而存在。
但是,当我需要从 WCF 服务项目(或即 WPF 项目)调用相同的业务逻辑方法时,我将无法使用我的 DbContextManager 类,因为它依赖于 HttpContext。
我觉得我现在这样做完全错误,我正在与实体框架进行一场不必要的战斗。我错过了什么? Entity Framework 是否适合这些类型的解决方案?现在肯定不是那种感觉:-)
非常感谢任何帮助或提示!
提前致谢。
【问题讨论】:
-
看到您的数据库上下文被部署在服务层中真是令人恐惧。为什么不直接在 DAL 中显式加载实体,而不是冒泡延迟查询?也许更有针对性、更小的服务将有助于缓解臃肿,并帮助您避免需要将数据库直接冒泡。
-
嗨,大卫,感谢您的意见。 “可怕”,这是一个大词;-) 在我的服务层?我不确定你是什么意思。当请求结束时,它会在 MVC 应用程序中释放。在我看来,那里没有服务层。您是否可以制作“显式加载实体”的代码 sn-p ?我不确定这到底是什么意思。
-
查看我的答案stackoverflow.com/questions/29637516/…它可能会给你一些想法。
-
@BoMortensen 很抱歉造成混乱。我在全局 asax 中处理 db 上下文的问题是,您已将数据库完全绑定到 Web 项目 (MVC)。没有关注点分离,也没有控制反转。对我来说,在 n 层应用程序中这是一个非常可怕的地方。至于显式加载实体,每当您使用 ToList、ToArray 等解决查询时,您就是将查询的实体显式加载到内存中。这使您可以在离开 DAL 之前巧妙地处理您的上下文。
-
大卫:不用担心 :-) 我绝对明白你关于 global.asax 文件的意思。这正是我的问题:它与 DAL 的耦合太紧密了。然后我必须对急切加载进行一些修改,希望它会更有意义;-)
标签: c# asp.net-mvc entity-framework wcf n-tier-architecture