【问题标题】:.NET Entity framework project layout (architecture).NET Entity framework 项目布局(架构)
【发布时间】:2009-02-14 12:56:14
【问题描述】:

我正在尝试确定如何最好地构建 .NET 实体框架项目以实现良好的分层方法。到目前为止,我已经在一个玩家拥有和操作行星的基于浏览的游戏中进行了尝试。我是这样得到它的:

网站

这包含所有的前端。

C# 项目 - MLS.Game.Data

这包含带有我所有数据映射的 EDMX 文件。这里没有太多其他内容。

C# 项目 - MLS.Game.Business

这包含我称之为“经理”的各种类,例如 PlanetManager.cs。行星管理器具有各种用于与行星交互的静态方法,例如 getPlanet(int planetID),它将从 MLS.Game.Data 返回生成的代码对象。

从网站上,我会做这样的事情:

var planet = PlanetManager.getPlanet(1);

它从 MLS.Game.Data(从 EDMX 生成)返回一个 Planet 对象。它有效,但它在一定程度上困扰着我,因为这意味着我的前端必须引用 MLS.Game.Data。我一直觉得 GUI 应该只需要引用业务项目。

此外,我发现我的经理课程往往会变得非常繁重。我最终会在其中添加几十个静态方法。

所以...我的问题是 - 其他人如何布置他们的 ASP EF 项目?

编辑

不过,还有一些其他项目让我感到困扰。例如,假设我有我的 Planet 对象,它也是由向导生成的代码。如果有一天我的星球需要有一个专门的属性,比如说“人口”,它是基于星球对象的其他属性的某种计算。我想创建一个继承自 Planet 的新类然后返回它吗? (嗯,不知道这些类是否被 EF 密封?)

谢谢

【问题讨论】:

  • 回应您的编辑 - 这就是数据和丰富对象分离的地方。丰富的对象了解如何在封装修改它们的操作的同时公开它们的属性。 DTO 仅用于将数据传输到持久层,不需要任何逻辑。

标签: c# asp.net entity-framework architecture web-architecture


【解决方案1】:

您可以尝试以下方法来改进:

  • 使用 EF 获取数据层中的 DTO,然后使用这些 DTO 在业务层中填充更丰富的业务对象。只有这样您的 UI 才需要引用业务层。
  • 一旦您创建了丰富的业务对象,您就可以开始从管理器类中内化一些逻辑,从而有效地清理业务层。

我个人更喜欢更丰富的模型而不是管理器模型,因为正如您所说,您最终会得到大量静态方法,最终不可避免地会在其他静态方法中链接在一起。我觉得这太混乱了,更重要的是,在任何给定时间点都难以理解和保证对象的一致性。

如果您将逻辑封装在类本身中,则无论外部调用者的性质如何,您都可以更加确定对象的状态。

顺便问一个好问题。

【讨论】:

  • 我喜欢你的想法——但是,你不会重复很多工作吗?例如,如果 DTO 具有各种属性,您可能会在“更丰富”版本的类中再次创建所有这些属性。对吗?
  • 在附加之后 - 您是否曾经在 BLL 层中创建了从数据层中的 DTO 继承的类?这将启用一些定制。想法?坏主意?
  • 继承会增加层之间的耦合(而不是减少它),您最终可能会遇到循环引用依赖关系,这无论如何都会破坏它。是的,会有一些重复,但请记住 EF 可以生成你的 DTO,所以我不会太担心..
  • 当然,这总是与个人偏好和特定项目的性质有关,但对我来说,“胜利”在于缩减经理课程的使用。他们很少对我有感觉:)
【解决方案2】:

恕我直言,您当前的布局很好。在您调用它时,您的 UI 引用“数据”层是完全正常的。我认为您的担忧可能是由于术语而引起的。您描述的“数据”通常被称为“业务对象”(BOL)层。然后,一个常见的布局将是有一个业务逻辑层 (BLL),它是您的“经理”层和一个数据访问层 (DAL)。在您的场景中,LINQ to Entites(假设您将使用它)是您的 DAL。一个正常的参考模式将是:-

UI 引用 BLL 和 BOL。 BLL 引用 BOL 和 DAL (LINQ to Entites)。

查看this series of articles了解更多详情。

【讨论】:

  • 我明白你的意思。尽管在 EF 的情况下,我别无选择,只能将我的 BOL 与 DAL 结合起来,因为 BOL 是由制作 EF 的向导生成的。我错过了什么吗?
  • 对不起,我的陈述有误。 EF 不是您的 DAL。无论您用来从数据库中获取项目的任何层都将是您的 DAL,大概是 LINQ to Entitites。在那种情况下,我描述的模型仍然成立。您生成的 BOL 仍然只是一个 BOL,使用 EF。我将编辑帖子。
【解决方案3】:

至于您的第二个问题(在 EDIT 之后),如果您需要或想要向您的 EF 对象添加功能,您可以使用部分类。右键单击 EDMX 文件并选择查看代码。

或者,如果这还不够,您可以放弃设计器并编写自己的启用 EF 的类。

这里有两个选项的(简要)讨论 - http://msdn.microsoft.com/en-us/library/bb738612.aspx

【讨论】:

    【解决方案4】:

    关于“编辑”部分的第二个问题:

    如果我没记错的话,EF 生成的类不是密封的,它们是 PARTIAL 类,因此您可以轻松地扩展这些类,而无需接触生成的文件本身。

    生成的类将是:

    public partial class Planet : global::System.Data.Objects.DataClasses.EntityObject
    {
     ...
    }
    

    这样您就可以轻松创建自己的“PlanetAddons.cs”(或任何您想调用的名称)来扩展此类:

    public partial class Planet 
    {
     property int Population {get; set;} 
     ...
    }
    

    相当整洁,嗯?无需派生和创建人工对象层次结构......

    马克

    【讨论】:

      【解决方案5】:

      我不是专家,但这对我来说听起来不错。这与我的解决方案中的类似,只是我只是将 EF 项目与业务项目合并。我的解决方案没有那么大,而且我的对象不需要很多智能,所以对我来说没问题。我的每个静态助手类也有很多不同的方法。

      如果您不想让表示层知道数据访问层,那么您必须创建一些中间类,这可能需要做很多工作。那么您当前的设置有什么问题?

      【讨论】:

      • 依赖关系使单个层的测试和修改更加困难。对于一个小项目,它可能并不重要。但是对于规模更大、生命周期更大的项目,通常建议通过使用控制容器的反转和定义的接口使层之间的依赖关系为 0。目前这对于 Entity Framework 生成的类来说是相当棘手的。
      【解决方案6】:

      您的布局看起来不错。 我会添加一个实用程序/公共层

      网页界面
      业务层
      数据对象
      实用程序层

      【讨论】:

        【解决方案7】:

        我会将 DTO 添加到您的业务层,它们是数据层中实体的“哑对象”表示(即仅属性)。然后您的“经理”类可以返回它们,例如:

        class PlanetManager
        {
            public static PlanetDTO GetPlanet(int id) { // ... }
        }
        

        而你的 UI 只能通过 POCO 处理 BLL 层;管理器(我称之为“映射器”类)处理对象和数据层之间的所有转换。此外,如果您需要扩展该类,您可以在 DTO 对象上拥有一个“虚拟”属性,并让 Manager 将其转换回其组件。

        【讨论】:

          猜你喜欢
          • 2010-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-07
          • 1970-01-01
          • 2011-04-27
          • 1970-01-01
          • 2020-02-11
          相关资源
          最近更新 更多