这个问题与我在这里提出的另一个问题(Entity Framework 4.2 - How to implement TPT-Inheritance with Database-generated Primarykey Value?)有关,并且应该简单地澄清一下,如果我对主题中所述问题的假设正确与否.
问题(详细):
- 我想使用 EF (4.1) 访问一个已经存在的数据库
- 数据库对其表的主键值的生成有一些限制(有一个 UDF,它采用表名并返回下一个可用 ID)
- 为了让我自己尽可能简单,我的第一种方法是定义数据库触发器(在插入之前),它调用 ID 生成 UDF 以在插入新数据行时设置新 ID
- 然后我将我的 EDM 的 csdl 中相应实体的 StoreGeneratedPattern 属性设置为“Identity”,以便在将新生成的 ID 保存到数据库后将它们设置在实体对象中
结果是:
当我创建一个新的实体对象,将其添加到 DbContext 并在其上调用 SaveChanges 时,相应的数据行被插入到数据库中,但实体没有使用新的数据库生成的 ID 进行更新。当我尝试一次保存更多时,我意识到了这一点,它们之间存在关联(父子实体),因为子实体的外键属性无法正确设置,因为父实体的新 ID 未知数据库上下文。
这就是我问上面提到的关于 TPT 继承的问题的原因。
经过几天的研究并尝试了我想到的一切来解决这个问题,我想我意识到,这根本行不通。尽管 MSDN 上的 StoreGeneratedPattern 枚举文档和博客中的一些解释表明,应设置 StoreGeneratedPattern.Identity 以检索生成的值,但当数据库在插入新行时生成值时,主键并不适用与数据库触发器。
在考虑了很长时间之后,这对我来说似乎是完全合乎逻辑的,因为 EF 需要一些标准来检索数据库生成的值,我认为在大多数情况下这将是实体的身份。对于设置为自动增量(或标识列,...)的数据库列,这可能没有问题,因为 DBMS 提供了一些功能来检索最后插入的标识值(例如 MSSQL 中的@@identity)。但是,当使用触发器生成新的标识值时,EF 显然不知道如何查询新插入的行(而且我也无法想象任何好的独立于数据库的方式来执行此操作)。
所以我的实际问题是:上面的假设是正确的还是我在这里忽略了一些重要的东西?
提前感谢您对此的任何澄清/启发。
编辑(后续问题):
在阅读了 Ladislav 的回答后,出现了另一个问题:
如果我在 CSDL 中设置 StoreGeneratedPattern,我是否必须在 SSDL 中将其设置为相同的值(反之亦然)?edm 设计器的补丁暗示了这种情况,因为当您在 CSDL 中更改 StoreGeneratedPattern(通过设计器)时,它会自动同步 SSDL 中的 StoreGeneratedPattern。