我相信这是一个原因,尽管我可能看不到完整的画面,可能只是猜测。
情况
事实上,唯一的方法(我见)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策略。
这两个问题是不相关的。你确定数据真的在'Developers' table =你确定你已经正确配置了TPC吗? 'OfType'的问题与TPC/TPT无关。这就是'OfType'的工作原理。 – 2012-02-23 10:11:33
OfType确实在tpt ... 中的工作方式,我将每手的值插入到数据库(开发人员开发人员和高级开发人员仅限高级开发人员),OfType()只给我开发人员,没有高级开发人员听起来有点奇怪。 我设置了所有像这里所说的http://cockneycoder.wordpress.com/2010/11/25/entity-framework-and-concrete-table-per-type-inheritance/ –
relascope
2012-02-24 10:31:43