简体   繁体   English

实体框架 - 不映射到数据库表的抽象基类

[英]Entity Framework - Abstract base class without mapping to DB table

I have a situation where I have 4-5 very similar classes which I'd like to re-factor to use an abstract base class. 我有一种情况,我有4-5个非常相似的类,我想重新考虑使用抽象基类。 The idea behind this would be allow methods which could be used by each class whilst adhering to DRY principles. 这背后的想法是允许每个类可以使用的方法,同时遵守DRY原则。

The problem I have is that these classes are Entity classes generted from EF4 and each time I try to alter my model it seems to break down. 我遇到的问题是这些类是从EF4生成的实体类,每次我尝试改变我的模型时它似乎都会崩溃。

What's the best/recommended, method to add a base class into my EF model and make the existing classes in the model inherit from this as a base? 将基类添加到我的EF模型中并使模型中的现有类继承作为基础的最佳/推荐方法是什么? At the moment I've got no problem adding the base class, giving it an ID property as it seems to require, and then creating the inheritence, but EF then moans about 目前我没有问题添加基类,给它一个ID属性,因为它似乎需要,然后创建继承,但EF然后呻吟关于

'Error 3024: Problem in mapping fragments starting at line 18563:Must specify mapping for all key properties (MyBaseType.ID) of the EntitySet MyBaseType.'

In this situation I don't want the base type to be persisted to the DB, purely used as a container for base methods common to all the classes which inherit from it. 在这种情况下,我不希望将基类型持久化到DB,纯粹用作从其继承的所有类共有的基本方法的容器。 It feels like I'm missing something simple here but I can't for the life of me see it. 感觉我在这里错过了一些简单的东西,但我不能为我的生活看到它。

Any ideas on how to add in a base class in this way? 有关如何以这种方式添加基类的任何想法? Or should I just be adding the base class in code and bypassing the model somehow? 或者我应该只是在代码中添加基类并以某种方式绕过模型?

EDIT: As further information, take an example where there are say 3 types, MortageApplicationForm, BankAccountApplicationForm and CreditCardApplication form. 编辑:作为进一步的信息,举例说明有3种类型,MortageApplicationForm,BankAccountApplicationForm和CreditCardApplication表单。 They are currently stored in 3 different tables, with a set of different fields. 它们目前存储在3个不同的表中,具有一组不同的字段。 What I'm trying to do, is create a base class of say 'Form' which will have the common fields in it. 我正在尝试做的是创建一个类似'Form'的基类,它将包含公共字段。

At a simple level, say that each table has a primary key ID field called, 'CreditCardFormID', 'BankAccountFormID' etc What I'd like to do it create a base 'Form' class with a property 'ID' which for the case of one table will map to 'CreditCardFormID' and another 'BankAccountFormID'. 在一个简单的层面上,假设每个表都有一个名为'CreditCardFormID','BankAccountFormID'等的主键ID字段。我想做的是创建一个带有属性'ID'的基础'Form'类,用于案例一个表将映射到'CreditCardFormID'和另一个'BankAccountFormID'。

I'm happy to do this mapping in partial classes (as I don't want to persist 'ID' to the DB) I simply want to use it in code, so I can write generic methods for things like LoadForm(int ID) without needing to write huge switches for each entity type, or specific methods for each entity type. 我很高兴在部分类中执行此映射(因为我不想将'ID'持久保存到DB中)我只是想在代码中使用它,因此我可以为LoadForm(int ID)之类的东西编写泛型方法无需为每个实体类型编写大型开关,或为每个实体类型编写特定方法。

I managed to find a work around for this by rejigging things slightly. 我设法通过略微重新调整事情来找到解决方法。 Firstly, I did not have the time available to rework the model (which I think would have been the best solution) too much of the system has already been developed with the existing structure to rip it all apart at this point. 首先,我没有时间来重新设计模型(我认为这是最好的解决方案)太多的系统已经用现有的结构开发,以便在这一点上将它们分开。

The solution so far, has been to create a static helper class to contain business logic which is generic accross in my example, the 3 different account types. 到目前为止,解决方案一直是创建一个静态帮助程序类来包含业务逻辑,这在我的示例中是通用的,即3种不同的帐户类型。

This was coupled with an 'IAccount' interface, allowing the helper class to take an IAccount instance as a parameter (allowing the passing of any particular account type.) This interface contained all the common properties accross the 3-4 concrete classes. 这与“IAccount”接口相结合,允许辅助类将IAccount实例作为参数(允许传递任何特定的帐户类型。)此接口包含3-4个具体类的所有常见属性。 It was important to note that in order to create generic methods which I could call on all the classes I was not able to use any other properties specific to the class. 重要的是要注意,为了创建我可以在所有类上调用的泛型方法,我无法使用特定于该类的任何其他属性。

Within the helper methods, I needed to switch my concrete XYZEntities instance to a more generic 'ObjectContext' object and then use the methods such as 'AddObject' rather than 'AddBankAccountForm', 'AddCreditCardForm' etc explicitely. 在辅助方法中,我需要将具体的XYZEntities实例切换为更通用的“ObjectContext”对象,然后明确地使用诸如“AddObject”之类的方法而不是“AddBankAccountForm”,“AddCreditCardForm”等方法。 This involved a tiny bit of GetType()'ing to ensure the object was passed to the correct ObjectSet, but seems to work as desired. 这涉及到一小部分GetType(),以确保将对象传递给正确的ObjectSet,但似乎可以按照需要工作。

There are 3 patterns for this: 这有3种模式:

  • Table per Class Hierarchy . 每个类层次结构的表 All concrete types in the inheritance heirarchy are stored in one table. 继承层次结构中的所有具体类型都存储在一个表中。
  • Table per Type . 每种类型的表 Each type in the inheritance is stored in it's own table. 继承中的每种类型都存储在它自己的表中。
  • Table per Concrete class . 每个混凝土类的表 A table for each concrete class but no table for the abstract class. 每个具体类的表,但没有抽象类的表。

In your case with the existing tables the Table per Concrete class looks like the best fit. 在您使用现有表的情况下,Table per Concrete类看起来最合适。

There is a good description of these options in this book 本书中对这些选项有很好的描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM