2012-02-23 86 views
1

我使用EF与TPC和我有多重继承可以说我有实体框架TPC多重继承

员工(摘要)

开发者(从雇员继承)

SeniorDeveloper(继承来自Developer)

我在数据库中插入了一些行,EF正确地读取它们。

但是 当我插入新的SeniorDeveloper时,将值写入SeniorDeveloper AND Developer数据库表,因此查询开发人员(context.Employees.OfType())也会获得最近添加的SeniorDevelopers。

有没有办法告诉EF,它应该只存储在一张表中,还是EF为什么会回退到TPT策略?

+0

这两个问题是不相关的。你确定数据真的在'Developers' table =你确定你已经正确配置了TPC吗? 'OfType'的问题与TPC/TPT无关。这就是'OfType'的工作原理。 – 2012-02-23 10:11:33

+0

OfType确实在tpt ... 中的工作方式,我将每手的值插入到数据库(开发人员开发人员和高级开发人员仅限高级开发人员),OfType ()只给我开发人员,没有高级开发人员听起来有点奇怪。 我设置了所有像这里所说的http://cockneycoder.wordpress.com/2010/11/25/entity-framework-and-concrete-table-per-type-in​​heritance/ – relascope 2012-02-24 10:31:43

回答

1

由于它看起来并不像EF支持与TPC的多重继承,我们最后使用的员工TPC来开发和SeniorDeveloper之间开发和TPT ......

+0

EF不正确, t支持与TPC的多重继承。对于EF> = 4.1它起作用(类型上的'OfType'只是简单地将这个类型的表和所有派生类型翻译成SQL中的UNION。 INSERTS只能插入所插入类型的表格中,而不能插入任何基本类型的表格中。由于EF 4.1使用EF 4.0的ObjectContext,我也怀疑它在EF 4.0中不受支持。 – Slauma 2012-05-24 15:51:54

1

我相信这是一个原因,尽管我可能看不到完整的画面,可能只是猜测。

情况

事实上,唯一的方法(我见)EF能够通过只读取仅列出非高级开发人员(您的查询用例)的TPT方案为Developer表将使用鉴别器,并且我们知道EF不使用TPT/TPC策略中的一个。

为什么?那么请记住,所有高级开发人员都是开发人员,因此他们只有一个Developer记录以及一个SeniorDeveloper记录是很自然的(也是必要的)。

唯一的例外是,如果Developer是抽象类型,在这种情况下,您可以使用TPC策略来删除Developer表。然而在你的情况下,Developer是具体的。

目前的解决方案

记住这一点,并没有在Developer表鉴别,只有这样,才能确定是否有任何开发商是一个非高级开发人员是通过检查,如果它是一高级开发者;换句话说,通过验证在SeniorDeveloper表或任何其他子类型表中没有开发人员的记录。

这听起来有点明显,但现在我们明白了为什么当它的基本类型(开发人员)具体(非抽象)时,必须使用和访问SeniorDeveloper表。

当前实现

我从记忆写这个,所以我希望这不是太掉,而这也是什么Slauma在另一则留言中提到。你可能想要启动一个SQL分析器并验证它。

它的实施方式是通过请求表的预测的联合。这些投影只是添加一个鉴别器,以某种编码方式声明他们自己的类型[1]。在联合集合中,行可以根据这个鉴别器进行过滤。

[1]如果我没有记错,它就像这样:0X为基本类型,0X0X为联合中的第一个子类型,0X1X为第二个子类型,依此类推。

权衡#1

我们已经可以识别一个权衡:EF可以存储鉴别表中,或在“运行时”可以“产生一个”。

  • 存储的鉴别器的缺点是它的空间利用率较低,并且可能“丑陋”(如果这是一个参数)。优点是查询性能在一个非常特殊的情况下(我们只想要基地类型的记录)。
  • “运行时间”鉴别器的缺点是查找性能不如同样的用例。优点是它更节省空间。

乍一看,似乎有时我们可能更愿意为查询性能交易一点点空间,而EF不会让我们这样做。

实际上,它并不总是清楚什么时候;通过请求两个表的UNION,我们只查找两个索引而不是一个索引,性能差异可以忽略不计。使用单一级别的继承,它不会比2倍差(因为所有子类型集合都是不相交的)。但是,等等,还有更多。

权衡#2

请记住,我说的是存储,鉴别方法的性能优势将只出现在特定的使用情况,我们查找的基本类型的记录。这是为什么?那么,如果你正在寻找可能是或可能不是高级开发者[2]的开发者,那么你不得不查找SeniorDeveloper。虽然这一点看起来很明显,但可能不那么明显的是,EF无法预先知道这些类型是否只属于某种类型。这意味着在最坏的情况下,它必须发出两个查询:Developer表中有一个,如果结果集中有一个高级开发人员,则在SeniorDeveloper表中有第二个。

不幸的是,额外的往返可能具有比两个表的工会更大性能的影响。 (我可能说,我没有验证它。)更糟糕的是,它增加了每个在结果集中有一行的子类型。想象一下有3种,5种甚至10种亚型的类型。

这就是你的权衡#2。

[2]请记住,这种操作可能来自应用程序的任何部分,而解决折衷必须在全局范围内完成以满足所有进程/应用程序/用户。此外夫妇,与事实EF团队必须做出这些权衡所有的EF用户(虽然这是事实,他们可以添加一些配置为这些类型的取舍)。

另一种可能

通过批量SQL查询,将有可能避免多次往返。 EF将不得不向服务器发送一些过程逻辑以进行条件查找(T-SQL)。但由于我们已经建立在权衡#1的性能优势是最有可能可以忽略不计在许多情况下,我不知道这将永远是值得的。也许有人可以为此打开问题单以确定它是否有意义。

结论

在未来,也许有人可以与一些有创意的解决方案,这种特定情况下优化了几个典型的操作,然后提供一些配置交换机时,优化涉及这样的取舍。

眼下不过,我认为EF已经选择了一个公平的解决方案。以一种奇怪的方式,它几乎更干净。

的几个注意事项

  • 我认为使用工会的是在某些情况下应用的优化。在其他情况下,它将是一个外连接,但使用鉴别符(和其他所有内容)保持不变。

  • 你提到的多重继承,这有点糊涂了最初。在通用的面向对象的说法中,多继承是一种类型有多种基类型的构造。许多面向对象的类型系统不支持它,包括CTS(由所有.NET语言使用)。你的意思是在这里。

  • 您也提到,EF将“回退”到TPT策略。在Developer/SeniorDeveloper的情况下,TPC策略与TPT策略的结果相同,因为Developer是具体的。如果你真的想要一个表,你必须使用TPH策略。

+0

+1为您的伟大工作!无论如何,我还没有参加过这个项目(并在SO上)一段时间,所以我现在就读了它。很好解释! (没有验证) – relascope 2015-04-17 21:08:49