wpf 使用实体框架作为数据访问层时,如何实现业务逻辑层?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12077593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 05:04:53  来源:igfitidea点击:

How do you implement a business logic layer when using entity framework as data access layer?

c#.netwpfentity-frameworkbusiness-logic-layer

提问by user938866

Say i have 3 layers

说我有3层

layer 1: WPF Project (contains: xaml, viewmodels, mvvm framework)

第1层:WPF项目(包含:xaml、viewmodels、mvvm框架)

layer 2: business logic layer (contains: plain c# classes)

第 2 层:业务逻辑层(包含:普通 c# 类)

layer 3: entity framework (contains: repository/data access classes)

第 3 层:实体框架(包含:存储库/数据访问类)

when you dont want to expose your DAL(layer 3) to View(layer 1) how do you implement the business logic layer well? im having a hard time putting values back and forth the BLL objects and DAL entities.

当您不想将 DAL(第 3 层)暴露给 View(第 1 层)时,您如何很好地实现业务逻辑层?我很难在 BLL 对象和 DAL 实体之间来回放置值。

can you please help?

你能帮忙吗?

采纳答案by daryal

Instead of exposing all of your DAL to View Layer, just exchange your domain objects (EF objects) between all layers. The structure may be similar to the following:

无需将所有 DAL 暴露给视图层,只需在所有层之间交换域对象(EF 对象)。该结构可能类似于以下内容:

  1. Presentation Layer-------- ^
  2. BLL --------------------------- | Data objects
  3. DAL (Repositories etc.)--- |
  1. 表示层-------- ^
  2. BLL --------------------------- | 数据对象
  3. DAL(存储库等)--- |

So, all of your layers will be disconnected; but they will share the same domain objects. In real world, you can implement a similar structure by creating a seperate dll for Entity Framework entities which is shared by all layers. Note that ObjectContext shall be only visible to DAL (by default, entities and object context are generated in the same dll, you need to seperate this into two dlls).

因此,您的所有图层都将断开连接;但它们将共享相同的域对象。在现实世界中,您可以通过为所有层共享的实体框架实体创建单独的 dll 来实现类似的结构。请注意,ObjectContext 应仅对 DAL 可见(默认情况下,实体和对象上下文在同一个 dll 中生成,您需要将其分成两个 dll)。

回答by Scott Scowden

Entity Framework doesn't work really well in a "disconnected" model. Unless something has changed, I've never been able to get it to work great easily.

实体框架在“断开连接”模型中不能很好地工作。除非某些事情发生了变化,否则我从来没有能够轻松地让它很好地工作。

You could use AutoMapper in Layer 2 to create ViewModels to present to Layer 1, but then you'd still have to send the changes back to Layer 3, which could be a pain.

您可以在第 2 层中使用 AutoMapper 创建要呈现给第 1 层的 ViewModel,但是您仍然必须将更改发送回第 3 层,这可能会很痛苦。

回答by Kasey Speakman

If you're only developing a small app that will not change in the foreseeable, then just do whatever is quickest now. If you want a long-term maintainable app, then let me put forth the following.

如果您只是在开发一个在可预见的时间内不会改变的小应用程序,那么现在就做最快的事情。如果你想要一个长期可维护的应用程序,那么让我提出以下内容。

The problem with this vertical layer approach is that whenever you need something in the view, you will have to add it to both the Business Layer (even if the business layer doesn't care about it), and the Data Layer. This requires your business layer to look like 1) UI views of the data 2) business views of the data and 3) the database representation of the data. That and/or you need a lot of mapping in-between layers. All of which dilutes business layer's actual purpose of representing business logic. What tends to happen then is that all the business logic gets migrated into transaction methods (that could just as well be static methods) to just change states on data objects. There's nothing at all wrong with that if your problem domain is nothing but CRUD with no complex logic. With complex logic, such business methods can get pretty tricky or even have undefined outcomes (because complex interdependencies on "fields" can be contradictory and hard to resolve).

这种垂直层方法的问题在于,每当您需要视图中的某些内容时,您都必须将其添加到业务层(即使业务层不关心它)和数据层。这要求您的业务层看起来像 1) 数据的 UI 视图 2) 数据的业务视图和 3) 数据的数据库表示。那和/或您需要在层之间进行大量映射。所有这些都淡化了业务层代表业务逻辑的实际目的。然后往往会发生的是,所有业务逻辑都被迁移到事务方法(也可以是静态方法)中,以更改数据对象的状态。如果您的问题域只是没有复杂逻辑的 CRUD,那完全没有错。复杂的逻辑,

Assuming you have complex logic, user views of data and business representations of data are often very different, and so UI views end up with specialized models of the data. If I were you, I just embrace this and use a simple version of the CQRS principle. That is, have the data for your UI views come from a different place than where your business operations are executed. In your case, I might have an EF Model in your DAL that only services your UI views, and gives them exactly what they need (whether by database views, stored procedures, or pre-compiled report tables). Then create a separate EF model that services only the needs for your Business entities. Then when you are ready to perform an actual business action, the UI's viewmodel action method can load the business object from the business EF model (or better yet, call an object factory from the business layer which does this) and run an appropriate action on the business object. Note that I'm also making the assumption here that your database is highly relational (mostly 2nd and 3rd normal form) and you are set on using EF.

假设您有复杂的逻辑,数据的用户视图和数据的业务表示通常非常不同,因此 UI 视图最终会使用专门的数据模型。如果我是你,我会接受这一点并使用 CQRS 原则的一个简单版本。也就是说,让 UI 视图的数据来自与执行业务操作的位置不同的位置。在您的情况下,我可能在您的 DAL 中有一个 EF 模型,它只为您的 UI 视图提供服务,并为它们提供所需的内容(无论是通过数据库视图、存储过程还是预编译的报告表)。然后创建一个单独的 EF 模型,该模型仅满足您的业务实体的需求。然后,当您准备好执行实际业务操作时,UI 的 viewmodel 操作方法可以从业务 EF 模型(或者更好的是,从执行此操作的业务层调用对象工厂)并对业务对象运行适当的操作。请注意,我还假设您的数据库是高度相关的(主要是第二和第三范式),并且您准备使用 EF。

I would not try to make your View Models into business logic. This makes your business logic not easily reusable on other platforms or applications (like web). MVVM should only service the UI. In my mind, the V (view) represents what the user sees and operates. The M (model) represents what the user chose on that view. And the VM (view model) translates between the two. Your program should then take the user's validated choices (UI model) and extract the needed data out of it to perform an appropriate business operation.

我不会尝试将您的视图模型变成业务逻辑。这使得您的业务逻辑不容易在其他平台或应用程序(如 Web)上重用。MVVM 应该只服务于 UI。在我看来,V(视图)代表用户看到和操作的内容。M(模型)代表用户在该视图上选择的内容。VM(视图模型)在两者之间进行转换。然后,您的程序应该采用用户经过验证的选择(UI 模型)并从中提取所需的数据以执行适当的业务操作。

回答by Rachel

Your ViewModelsareyour application in MVVM, so they should be handling things like data access through your Repository classes, or business logic (either directly, or indirectly using your validation classes).

ViewModelsMVVM的应用程序,因此它们应该处理诸如通过您的 Repository 类或业务逻辑(直接或间接使用您的验证类)访问数据之类的事情。

If you don't want to directly reference the classes, use an Interfacebut be aware that you'll need to have some way of passing your inherited class to your ViewModel. I once did a project where we had a library of shared interfaces, such IRepositoryinterfaces, and everything was imported/exported using MEF so the layers didn't reference each other directly.

如果您不想直接引用类,请使用 anInterface但请注意,您需要通过某种方式将继承的类传递给 ViewModel。我曾经做过一个项目,我们有一个共享接口库,这样的IRepository接口,所有的东西都是使用 MEF 导入/导出的,所以层不会直接相互引用。

The final (simplified) layout was:

最终(简化)布局是:

  • Models-> Contained plain data objects that could do simple validation on their own data (length, min/max values, etc) but that didn't do any advanced validation or business logic. Did not reference any other library.

  • Common-> Contained interfaces, utilities, and other commonly shared classes. Referenced the Model library only.

  • DAL-> Contained Data Access and Repositories based on repository interfaces found in Common library. Referenced Common library for interface definitions and utilities, and Model library because it contained the data models used or returned in data access calls

  • ViewModels-> Contained application and business logic. Referenced Common for its utilities and interfaces, and Models for the data models

  • Client-> Contained Views. Referenced Models and ViewModels so it could write DataTemplatesfor both object types

  • 模型-> 包含可以对自己的数据(长度、最小值/最大值等)进行简单验证但不进行任何高级验证或业务逻辑的普通数据对象。没有引用任何其他库。

  • 通用-> 包含的接口、实用程序和其他常见共享类。仅引用模型库。

  • DAL-> 基于公共库中的存储库接口的包含数据访问和存储库。接口定义和实用程序的引用通用库,以及模型库,因为它包含在数据访问调用中使用或返回的数据模型

  • ViewModels-> 包含的应用程序和业务逻辑。其实用程序和接口的引用通用,以及数据模型的模型

  • 客户端-> 包含的视图。引用模型和视图模型,以便它可以DataTemplates为两种对象类型编写

回答by Maarten

In addition to the answer by Daryal, you can define your business-objects in your BL to be POCO's, and use EF in your DAL layer to read them from or persist them to the database.

除了 Daryal 的回答之外,您还可以将 BL 中的业务对象定义为 POCO,并在 DAL 层中使用 EF 从数据库中读取它们或将它们持久化到数据库中。

If you define an repository-like interface in your BL (or unit-of-work, whatever naming you give it), and implement the interface in your DAL, then all you need is a little DI to get an instance of the repository-class without having to reference the DAL all the time. It works like a charm for me.

如果你在你的 BL(或工作单元,无论你给它起什么名字)中定义了一个类似存储库的接口,并在你的 DAL 中实现了这个接口,那么你所需要的只是一点点 DI 来获取存储库的实例 -类而不必一直引用 DAL。它对我来说就像一种魅力。

See hereand herefor more information.

请参阅此处此处了解更多信息。

回答by umlcat

Entity framework is suppouse to be used as "Logic Layer" by itself.

实体框架本身应该用作“逻辑层”。

Your idea may have some sense, to use combine technologies.

你的想法可能有一定的意义,使用组合技术。

Howevere, I think some of those Micros. libraries, where designed to be used separately, unless, otherwise explicitly combined & mentioned in their websites.

然而,我认为其中一些微。设计为单独使用的库,除非在其网站中明确组合和提及。

Good Luck.

祝你好运。

回答by suomi-dev

I second daryal and I have implemented this in some projects. It is absolutely OK to use POCO as business objects.

我是第二个 daryal,我已经在一些项目中实现了这一点。将 POCO 用作业务对象是绝对可以的。

Another approach instead of creating 2 projects (one for DB Context and one for Entities) is to use one DAL/DATA project only and reference it in BLL. Then inherit the POCO class in BLL and use that class in UI layer. Below is the basic sample code:

另一种替代创建 2 个项目(一个用于 DB 上下文,一个用于实体)的方法是仅使用一个 DAL/DATA 项目并在 BLL 中引用它。然后继承 BLL 中的 POCO 类并在 UI 层中使用该类。下面是基本的示例代码:

// assume this is EF generated POCO
namespace Owner.Project.Data{
    public partial class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
    }
}

// this is manually created class in BLL
using Owner.Project.Data;
namespace Owner.Product.Business{
    public class StoreProduct : Product {
        public bool Add (string productName){
            // TODO - add product using EF as you normally do
        }
    }
}

Now you can reference the BLL in your UI project and use StoreProduct class there. To achieve loosely coupled pattern, Of course you could also inherit the StoreProduct class from an IStoreProduct interface and make use of it in UI or web service but that is another topic.

现在您可以在您的 UI 项目中引用 BLL 并在那里使用 StoreProduct 类。为了实现松散耦合模式,当然您也可以从 IStoreProduct 接口继承 StoreProduct 类并在 UI 或 Web 服务中使用它,但这是另一个主题。