无法将 StoreGeneratePattern.Identity 与数据库触发器生成的主键值一起使用?

发布于 2024-12-23 01:40:39 字数 1494 浏览 5 评论 0原文

这个问题与我在这里问的另一个问题有关( 实体框架 4.2 - 如何使用数据库生成的主键值实现 TPT 继承? )并且应该简单地澄清一下,如果我对主题中所述问题的假设是对与不对。

问题(详细):

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

结果是:

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

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

经过几天的研究并尝试了我想到的解决这个问题的所有方法后,我想我意识到,这根本行不通。尽管 MSDN 上的 StoreGeneratePattern 枚举的文档和博客中的一些解释表明,应该设置 StoreGeneeratedPattern.Identity 来检索生成的值,但当数据库在插入新行时生成值时,对于结合主键来说情况并非如此与数据库触发器。

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

所以我真正的问题是:上面的假设是否正确,或者我是否忽略了这里重要的事情?

预先感谢您对此的任何澄清/启发。

编辑(后续问题):

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

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

This question is related to another question i asked here ( Entity Framework 4.2 - How to realize TPT-Inheritance with Database-generated Primarykey Value? ) and should simply clarify, if my assumptions, regarding the problem stated in the topic, are right or not.

The Problem (in detail):

  • I want to use EF (4.1) to access a database, that already exists
  • the database has some restrictions regarding the generation of primary key values for its tables (there is a UDF that takes a tablename and returns the next available ID)
  • To make things as easy as possible for myself, my first approach was to define database triggers (before insert) that call the ID-generating UDF to set the new ID on inserting a new datarow
  • Then i set the StoreGeneratedPattern properties of the corresponding entities in the csdl of my EDM to "Identity", so that the newly generated IDs would be set in the entity objects after saving them to the DB

The Result of this was:

When I created a new entity object, added it to the DbContext and called SaveChanges on it, the corresponding datarow was inserted in the database, but the entity was not updated with the new database-generated ID. I realized this when i tried to save more at once, that have associations to each other (parent-child), because the foreignkey properties of the child entities could not be set correctly, since the new ID of the parent was not known to the DbContext.

This is the reason I asked the above mentioned question concerning TPT inheritance.

After several days of research and trying everything that came to my mind to solve this problem, i think i realized, that this simply cannot work. Although the documentation of the StoreGeneratedPattern enum at MSDN and several explanations in blogs suggests, that StoreGeneratedPattern.Identity should be set to retrieve the generated value, when the DB generates a value on inserting a new row, this is not true for primary keys in conjunction with database triggers.

After thinking about that a long time, that seems perfectly logical to me, since the EF needs some criterium to retrieve database-generated values, and i think that would be in most cases the identity of an entity. For databasecolumns that are set to autoincrement (or identity-column, ...) that might be no problem, because the DBMS provides some functionality to retrieve the last inserted identity-value (e.g. @@identity in MSSQL). But when using a trigger to generate a new identity-value, the EF obviously doesnt know how to query the newly inserted row (and i cant imagine any good db-independent way to do this either).

So my actual question is: are the assumptions above correct or am I overlooking something important here?

Thanks in advance for any clarification/inspiration on this.

Edit (followup question):

After reading the answer from Ladislav another question arises:

If I set StoreGeneratedPattern in CSDL, do I have to set it to the same value in SSDL (and vice versa)? The patch for the edm designer implies that this is the case, because it automatically synchronizes the StoreGeneratedPattern in SSDL when you change it in CSDL (through the designer).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜柠檬 2024-12-30 01:40:39

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

The StoreGeneratedPattern.Identity should work. If you set it in EF Designer make sure that it was correctly configured in both SSDL and CSDL parts of EDMX file (open it as XML to check it). There was a bug in EF designer which caused correct setting only in CSDL so SQL part didn't know that new ID must be selected from the database after insert. This bug was in some rare cases solved by installing VS 2010 SP1 and it should be definitely solved by special patch.

羁客 2024-12-30 01:40:39

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

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

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

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

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

I had the same problem: one of the column was set with trigger.

But it appeared that I did have troubles with VS edmx designer ('Identity' hadn't been set), and it helped fix it manually (one model had correct value, but other didn't).

Then we got "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries". That was easily fixed following instuctions here

If I set StoreGeneratedPattern in CSDL, do I have to set it to the
same value in SSDL (and vice versa)?

Yes, it seems to not work without changes to both CSDL and SSDL

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文