使用StoreGeneratedPattern.Identity与数据库触发器生成的主键值不可能?

时间:2011-12-27 14:06:54

标签: entity-framework-4.1 identity dbcontext database-trigger

这个问题与我在这里提出的另一个问题(Entity Framework 4.2 - How to realize TPT-Inheritance with Database-generated Primarykey Value?)有关,如果我的假设是关于主题中陈述的问题,那么应该澄清一下。

问题(详情):

  • 我想使用EF(4.1)访问已存在的数据库
  • 数据库对其表的主键值的生成有一些限制(有一个UDF,它接受一个表名并返回下一个可用的ID)
  • 为了让自己尽可能简单,我的第一种方法是定义数据库触发器(插入之前),调用生成ID的UDF以在插入新数据流时设置新ID
  • 然后我将我的EDM的csdl中相应实体的StoreGeneratedPattern属性设置为“Identity”,以便在将实体对象保存到数据库后将在实体对象中设置新生成的ID

结果是:

当我创建一个新的实体对象,将其添加到DbContext并在其上调用SaveChanges时,相应的数据行已插入数据库中,但实体未使用新的数据库生成的ID进行更新。我意识到这一点,当我试图一次保存更多,彼此有关联(父子),因为子实体的foreignkey属性无法正确设置,因为父母的新ID不知道的DbContext。

这就是我提出上述TPT继承问题的原因。

经过几天的研究并尝试了解决这个问题的一切,我想我意识到,这根本行不通。虽然MSDN上StoreGeneratedPattern枚举的文档和博客中的几个解释都表明,StoreGeneratedPattern.Identity应该设置为检索生成的值,当DB在插入新行时生成一个值时,对于主键结合不是这样。使用数据库触发器。

在考虑了很长一段时间之后,这对我来说似乎是完全符合逻辑的,因为EF需要一些标准来检索数据库生成的值,而且我认为在大多数情况下这将是一个实体的身份。对于设置为autoincrement(或identity-column,...)的databasecolumns,可能没有问题,因为DBMS提供了一些功能来检索最后插入的identity-value(例如MSSQL中的@@ identity)。但是当使用触发器生成新的标识值时,EF显然不知道如何查询新插入的行(我无法想象任何好的与数据库无关的方法来执行此操作)。

所以我的实际问题是:上述假设是正确还是我忽略了重要的事情?

提前感谢您对此的任何澄清/启发。

编辑(后续问题):

在阅读Ladislav的答案之后,出现了另一个问题:

如果我在CSDL中设置StoreGeneratedPattern,我是否必须在SSDL中将其设置为相同的值(反之亦然)? edm设计器的补丁意味着这种情况,因为当您在CSDL中更改它时,它会自动同步SSDL中的StoreGeneratedPattern(通过设计器)。

2 个答案:

答案 0 :(得分:1)

StoreGeneratedPattern.Identity应该有效。如果在EF Designer中设置它,请确保在EDMX文件的SSDL和CSDL部分中正确配置它(将其打开为XML以进行检查)。 EF设计器中存在一个错误,该错误仅在CSDL中导致正确设置,因此SQL部分不知道在插入后必须从数据库中选择新ID。这个错误是在installing VS 2010 SP1解决的一些罕见案例中,它应该由special patch明确解决。

答案 1 :(得分:0)

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

但似乎我确实遇到了VS edmx设计师的麻烦('身份'尚未设置),并且它帮助手动修复它(一个模型具有正确的值,但其他模型没有)。

然后我们得到“存储更新,插入或删除语句影响了意外的行数(0)。实体可能已被修改或删除,因为实体已加载。刷新ObjectStateManager条目”。在here

之后,这很容易解决
  

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

是的,如果不更改CSDL和SSDL

,它似乎无效