3

这个问题与我在这里提出的另一个问题(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。

4

2 回答 2

1

StoreGeneratedPattern.Identity应该工作。如果在 EF 设计器中设置它,请确保它在 EDMX 文件的 SSDL 和 CSDL 部分中都正确配置(以 XML 格式打开以检查它)。EF 设计器中有一个错误导致仅在 CSDL 中正确设置,因此 SQL 部分不知道插入后必须从数据库中选择新 ID。这个错误在极少数情况下通过安装 VS 2010 SP1解决了,它肯定应该通过特殊补丁解决。

于 2011-12-27T14:40:33.900 回答
0

我遇到了同样的问题:其中一列设置了触发器。

但似乎我确实在使用 VS edmx 设计器时遇到了麻烦(“身份”尚未设置),它有助于手动修复它(一个模型具有正确的值,但另一个没有)。

然后我们得到“存储更新、插入或删除语句影响了意外数量的行 (0)。自加载实体以来,实体可能已被修改或删除。刷新 ObjectStateManager 条目”。按照这里的说明,这很容易解决

如果我在 CSDL 中设置 StoreGeneratedPattern,我是否必须在 SSDL 中将其设置为相同的值(反之亦然)?

是的,如果不更改 CSDL 和 SSDL,它似乎无法工作

于 2012-07-05T08:26:58.910 回答