gpt4 book ai didi

c# - SET IDENTITY_INSERT [table] ON 不工作

转载 作者:行者123 更新时间:2023-11-30 23:04:49 27 4
gpt4 key购买 nike

我想在我指定 Id 的地方插入一些记录,以便在我希望保持现有关系完整性的地方迁移数据。

为此,我直接在表上的 SSMS 中运行了这个命令:

SET IDENTITY_INSERT [CRMTItem] ON;

然而,当我从 C# 中插入一个 ID 为 1 的项目时,该 ID 仍在从 850 左右递增。

我从 EDMX 中删除了实体并再次从数据库中更新,但结果相同。

这是我的插入代码,如您所见,我在插入之前确保 Id 确实为 1,但这只是被忽略了..

var crmtItem = new CRMTItem();

crmtItem.Id = adv.PrimaryId;
crmtItem.ProjectTitle = adv.ProjectTitle;
crmtItem.CreatedByUser = (adv.CreatedBy == null) ? (Guid?)null : new Guid(adv.CreatedBy);
crmtItem.Opportunity = (adv.Opportunity == null) ? (Guid?)null : new Guid(adv.Opportunity);
crmtItem.BidNoBid = adv.Bnb;
crmtItem.SPUrl = adv.SPUrl;
crmtItem.BnbId = (adv.BnbId == null) ? (Guid?)null : new Guid(adv.BnbId);
crmtItem.Stage = adv.ProjectStage;
crmtItem.Confidential = adv.Confidential;
crmtItem.OpportunityStatus = adv.OpportunityStatus;
crmtItem.OpportunityNumber = adv.OpportunityNumber;
crmtItem.CRMTNumber = adv.CrmtNumber;
crmtItem.ProjectNumber = adv.ProjectNumber;
crmtItem.Sector = adv.Sector;
crmtItem.Service = adv.Service;
crmtItem.CreatedDate = adv.CreatedDate;
crmtItem.Archive = adv.Archive;
crmtItem.ProjectManager = adv.ProjectManager;
crmtItem.WorkTeam = adv.WorkTeam;
crmtItem.Custodian = adv.Custodian;

db.CRMTItems.Add(crmtItem);

if (adv.PrimaryId == 1 || adv.PrimaryId == 2 || adv.PrimaryId == 3)
{
await db.SaveChangesAsync();
}

我也尝试在插入项目之前添加这一行

db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[CRMTItem] ON");

但是还是不行。

根据我发现的另一个 SO 问题,我接下来尝试了这个:

db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[CRMTItem] ON");
db.CRMTItems.Add(crmtItem);

if (adv.PrimaryId == 1)
{
await db.SaveChangesAsync();
}
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[CRMTItem] OFF");
transaction.Commit();

现在我得到一个错误

Explicit value must be specified for identity column in table 'CRMTItem' either when IDENTITY_INSERT is set to ON or when a replication user is inserting into a NOT FOR REPLICATION identity column.

我错过了什么吗?为什么控制我自己的数据如此困难?如果我做不到这一点,我将被迫在我的表中创建一个临时列来存储原始 (CDS) 表中的 id,这绝对是荒谬的,毕竟它是我的数据,为什么我不能选择列的值!?!?!

最佳答案

当您从数据库生成模型时 - Entity Framework 将使用 StoreGeneratedPattern.Identity 将所有标识列映射到模型属性。在您的情况下,据我了解,此类属性是 crmtItem.Id。当您插入 crmItem - Entity Framework 将忽略您为标识属性设置的值(如果您设置了任何值),因为它知道该值是由数据库提供的,所以它知道它是否尝试在插入语句 - 数据库将返回错误。

Entity Framework 不了解IDENTITY_INSERT,因此它将始终根据目标模型属性的StoreGeneratedPattern 元数据行事。如果它是 IdentityComputed - 无论您做什么,它都不会在插入中为其提供值(value)。如果它设置为 None - 那么它将提供一个值(无论如何)。

因此,对于您的情况,您需要在 EDMX 设计器中为目标属性 (CRMTItem.Id) 将此属性设置为 None。当然,这样做之后 - 您必须在插入时始终提供此值。

问题的另一部分,IDENTITY_INSERT 不被尊重,你已经解决了,但仍然值得一些解释。此设置是 session 范围的,因此当您只是在 SSMS 中执行它然后尝试从您的应用程序插入时 - 它没有效果:SSMS 和您的应用程序位于不同的 session 中。

当你这样做的时候:

db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[CRMTItem] ON");

这仍然在单独的 session 中执行,而不是在您的 SaveChanges 执行的同一 session 中。因此,要在同一 session 中同时执行 IDENTITY_INSERTSaveChanges - 您需要将它们包装在事务中,正如您已经知道的那样。

关于c# - SET IDENTITY_INSERT [table] ON 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49123642/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com