Linq实体和​​业务逻辑

时间:2021-04-26 06:46:36

Whenever I read an article on linq to entities, I sounds like I should embed my business logic in the generated entity-classes.

每当我阅读关于linq的实体文章时,我听起来应该将我的业务逻辑嵌入到生成的实体类中。

This would means that the "user" of the business-objects (controller, service-layer, ...) would have to know about the datacontext-object that's needed to use linq.

这意味着业务对象(控制器,服务层......)的“用户”必须知道使用linq所需的datacontext对象。

It would also mean that the DAL-logic and the business-logic will be mixed up.

这也意味着DAL逻辑和业务逻辑将混为一谈。

A lot of microsoft examples use some kind of DTO-approach. I'm not a big fan of the DTO pattern.

很多微软的例子都使用了某种DTO方法。我不是DTO模式的忠实粉丝。

So should I let the business-object encapsulate the linq-entity and provide access to it using properties, or should I stick with the DTO pattern?

那么我应该让业务对象封装linq-entity并使用属性提供对它的访问,还是应该坚持使用DTO模式?

What are your suggestions?

你有什么建议?

Thanks

3 个解决方案

#1


The entity model generates partial classes. In a project of mine I'm using an entity model inside a class library and added a few .cs files to it that add functionality to the default entity classes. (Mostly functions related to error and message logging to a database table and a method to import/export all data to XML.)

实体模型生成部分类。在我的项目中,我在类库中使用实体模型,并向其添加了一些.cs文件,为默认实体类添加了功能。 (主要与错误和消息记录到数据库表相关的函数以及将所有数据导入/导出到XML的方法。)

But true business logic is located in a second class library that refers to this entity class library.

但真正的业务逻辑位于引用此实体类库的第二个类库中。


Let's explain. First I created an entity model from a database. It contains a list of company names and addresses. I do this by choosing "New project|Class library" and then add an ADO.NET Entity Data Model to this library. The Entity model will be linked to my SQL Server database, importing the tables I need and auto-creates classes for the tables I want to access. I then add a second .cs file for every table that I want to expand. This would be a few raw methods that are strongly linked to the database. (Mostly import/export methods and error logging.) This I will call Entity.Model, which will compile to Entity.Model.dll.

Then I add a second project which will contain the business logic. Again, I use "New project|Class library" to create it and add Entity.Model.dll to it's references. I then start writing classes which will translate the database-specific classes to more logical classes. In general, I would not have to make many changes except that I will protect or hide certain fields and add a few calculated fields. The business logic would only expose the functionality that I want to access from my client application and not a single method more. Thus, if I don't allow the client to delete companies then the "Delete" function in the entity model will not be exposed in the business layer. And maybe I want to send a notification when a company changes their address, so I'll add an event that gets triggered when the address field of the company is changed. (Which will write a message log or whatever.) I'll call this business.logic and it compiles to Business.Logic.dll.

然后我添加了第二个包含业务逻辑的项目。我再次使用“New project | Class library”创建它并将Entity.Model.dll添加到它的引用中。然后我开始编写类,将特定于数据库的类转换为更逻辑的类。一般情况下,除了我将保护或隐藏某些字段并添加一些计算字段之外,我不需要做很多更改。业务逻辑只会公开我想从客户端应用程序访问的功能,而不是更多的单一方法。因此,如果我不允许客户删除公司,那么实体模型中的“删除”功能将不会在业务层中公开。也许我想在公司更改地址时发送通知,因此我将添加一个在公司地址字段更改时触发的事件。 (这将写一个消息日志或其他。)我将称之为business.logic,它编译为Business.Logic.dll。

Finally, I'll create the client application and will add a reference to Business.Logic.dll. (But NOT to the entity model.) I can now start to write my application and access the database through the business layer. The business layer will do validations, trigger a few events and do whatever else in addition to modifying the database through the entity model. And the entity model just serves to keep the database relations simple, allowing me to "walk through" the data through all foreign links in the database.

最后,我将创建客户端应用程序并添加对Business.Logic.dll的引用。 (但不是实体模型。)我现在可以开始编写我的应用程序并通过业务层访问数据库。除了通过实体模型修改数据库之外,业务层还将执行验证,触发一些事件并执行其他任何操作。实体模型只是用来保持数据库关系简单,允许我通过数据库中的所有外部链接“遍历”数据。

#2


I wouldn't edit the generated files as they are likely to change.

我不会编辑生成的文件,因为它们可能会更改。

What you could do is wrap them some query object and pass that around.

你可以做的是将它们包装成一些查询对象并传递它。

ayende makes a very good point about where the DAL should really live

ayende非常关注DAL应该居住的地方

Also, you should be a fan of viewmodels/dtos ;)

此外,你应该是viewmodels / dtos的粉丝;)

#3


I prefer to wrap calls to the entity classes in business classes. (Call it BC for short.) Each BC has several constructors, one or more of which allows the context to be passed to it. This allows one BC to call another BC and load related data in the same context. This also makes working with collections of BCs that need a shared context simpler.

我更喜欢将调用包装到业务类中的实体类。 (简称为BC。)每个BC都有几个构造函数,其中一个或多个构造函数允许将上下文传递给它。这允许一个BC调用另一个BC并在相同的上下文中加载相关数据。这也使得处理需要共享上下文更简单的BC集合。

In the constructors that don't take a context, I create a new context in the constructor itself. I make the context available through a read-only property that other BCs can access.

在不接受上下文的构造函数中,我在构造函数本身中创建了一个新的上下文。我通过其他BC可以访问的只读属性来提供上下文。

I write using the MVVM pattern. The nice thing about this approach is that so far I have been able to write my viewmodels without ever refering to the data context, just the BCs that form my models. Hence if I need to modify my data access (replace entity framework, or upgrade to version 4 when it is out of beta) my views and viewmodels are isolated from the changes required in the BCs.

我使用MVVM模式编写。关于这种方法的好处是,到目前为止,我已经能够编写我的视图模型而无需引用数据上下文,只是形成我的模型的BC。因此,如果我需要修改我的数据访问权限(替换实体框架,或者在测试结束时升级到版本4),我的视图和视图模型将与BC中所需的更改隔离开来。

Not sure this is the best approach, but so far I have liked the results. It does take tweaking to get the BCs designed correctly, but I end up with a flexible, extensible, and maintainable set of classes.

不确定这是最好的方法,但到目前为止我还是喜欢这个结果。确实需要通过调整才能正确设计BC,但我最终得到了一组灵活,可扩展且可维护的类。

#1


The entity model generates partial classes. In a project of mine I'm using an entity model inside a class library and added a few .cs files to it that add functionality to the default entity classes. (Mostly functions related to error and message logging to a database table and a method to import/export all data to XML.)

实体模型生成部分类。在我的项目中,我在类库中使用实体模型,并向其添加了一些.cs文件,为默认实体类添加了功能。 (主要与错误和消息记录到数据库表相关的函数以及将所有数据导入/导出到XML的方法。)

But true business logic is located in a second class library that refers to this entity class library.

但真正的业务逻辑位于引用此实体类库的第二个类库中。


Let's explain. First I created an entity model from a database. It contains a list of company names and addresses. I do this by choosing "New project|Class library" and then add an ADO.NET Entity Data Model to this library. The Entity model will be linked to my SQL Server database, importing the tables I need and auto-creates classes for the tables I want to access. I then add a second .cs file for every table that I want to expand. This would be a few raw methods that are strongly linked to the database. (Mostly import/export methods and error logging.) This I will call Entity.Model, which will compile to Entity.Model.dll.

Then I add a second project which will contain the business logic. Again, I use "New project|Class library" to create it and add Entity.Model.dll to it's references. I then start writing classes which will translate the database-specific classes to more logical classes. In general, I would not have to make many changes except that I will protect or hide certain fields and add a few calculated fields. The business logic would only expose the functionality that I want to access from my client application and not a single method more. Thus, if I don't allow the client to delete companies then the "Delete" function in the entity model will not be exposed in the business layer. And maybe I want to send a notification when a company changes their address, so I'll add an event that gets triggered when the address field of the company is changed. (Which will write a message log or whatever.) I'll call this business.logic and it compiles to Business.Logic.dll.

然后我添加了第二个包含业务逻辑的项目。我再次使用“New project | Class library”创建它并将Entity.Model.dll添加到它的引用中。然后我开始编写类,将特定于数据库的类转换为更逻辑的类。一般情况下,除了我将保护或隐藏某些字段并添加一些计算字段之外,我不需要做很多更改。业务逻辑只会公开我想从客户端应用程序访问的功能,而不是更多的单一方法。因此,如果我不允许客户删除公司,那么实体模型中的“删除”功能将不会在业务层中公开。也许我想在公司更改地址时发送通知,因此我将添加一个在公司地址字段更改时触发的事件。 (这将写一个消息日志或其他。)我将称之为business.logic,它编译为Business.Logic.dll。

Finally, I'll create the client application and will add a reference to Business.Logic.dll. (But NOT to the entity model.) I can now start to write my application and access the database through the business layer. The business layer will do validations, trigger a few events and do whatever else in addition to modifying the database through the entity model. And the entity model just serves to keep the database relations simple, allowing me to "walk through" the data through all foreign links in the database.

最后,我将创建客户端应用程序并添加对Business.Logic.dll的引用。 (但不是实体模型。)我现在可以开始编写我的应用程序并通过业务层访问数据库。除了通过实体模型修改数据库之外,业务层还将执行验证,触发一些事件并执行其他任何操作。实体模型只是用来保持数据库关系简单,允许我通过数据库中的所有外部链接“遍历”数据。

#2


I wouldn't edit the generated files as they are likely to change.

我不会编辑生成的文件,因为它们可能会更改。

What you could do is wrap them some query object and pass that around.

你可以做的是将它们包装成一些查询对象并传递它。

ayende makes a very good point about where the DAL should really live

ayende非常关注DAL应该居住的地方

Also, you should be a fan of viewmodels/dtos ;)

此外,你应该是viewmodels / dtos的粉丝;)

#3


I prefer to wrap calls to the entity classes in business classes. (Call it BC for short.) Each BC has several constructors, one or more of which allows the context to be passed to it. This allows one BC to call another BC and load related data in the same context. This also makes working with collections of BCs that need a shared context simpler.

我更喜欢将调用包装到业务类中的实体类。 (简称为BC。)每个BC都有几个构造函数,其中一个或多个构造函数允许将上下文传递给它。这允许一个BC调用另一个BC并在相同的上下文中加载相关数据。这也使得处理需要共享上下文更简单的BC集合。

In the constructors that don't take a context, I create a new context in the constructor itself. I make the context available through a read-only property that other BCs can access.

在不接受上下文的构造函数中,我在构造函数本身中创建了一个新的上下文。我通过其他BC可以访问的只读属性来提供上下文。

I write using the MVVM pattern. The nice thing about this approach is that so far I have been able to write my viewmodels without ever refering to the data context, just the BCs that form my models. Hence if I need to modify my data access (replace entity framework, or upgrade to version 4 when it is out of beta) my views and viewmodels are isolated from the changes required in the BCs.

我使用MVVM模式编写。关于这种方法的好处是,到目前为止,我已经能够编写我的视图模型而无需引用数据上下文,只是形成我的模型的BC。因此,如果我需要修改我的数据访问权限(替换实体框架,或者在测试结束时升级到版本4),我的视图和视图模型将与BC中所需的更改隔离开来。

Not sure this is the best approach, but so far I have liked the results. It does take tweaking to get the BCs designed correctly, but I end up with a flexible, extensible, and maintainable set of classes.

不确定这是最好的方法,但到目前为止我还是喜欢这个结果。确实需要通过调整才能正确设计BC,但我最终得到了一组灵活,可扩展且可维护的类。