20

我有一个表,它为表的某些行存储一些额外的数据,例如:

public class QuoteExtra
{
    [Key]
    public int QuoteId { get; set; }
    // More fields here
}

我希望能够在我明确设置 PK 的表中添加行。

如果我只是像上面那样保留它,设置一个值并提交该行会导致该值被丢弃并替换为数据库中自动生成的值(并且该列被定义为实际模式中的 Identity 列)。

这似乎是正确的解决方案:

public class QuoteExtra
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int QuoteId { get; set; }
    // More fields here
}

然而,这反而让我例外:

当 IDENTITY_INSERT 设置为 OFF 时,无法在表“EnumTest”中插入标识列的显式值。

那么,如何编写我的课程以便能够在 EF 中设置主键的值?

编辑:

我尝试添加以下基于代码的迁移以将 IDENTITY_INSERT 设置为 ON:

public override void Up()
{
    Sql("SET IDENTITY_INSERT QuoteExtra ON");
}

我运行它并再次尝试,但得到与上述相同的异常。奇怪的是数据库确实反映了这个设置,并且直接对它运行 SQL 确实允许我为主键插入任意值 - 所以看起来实体框架本身正在执行这个规则,并且忽略了识别 IDENTITY_INSERT 不在事实设置为关闭。我需要在 EF 本身的某个地方设置它吗?

编辑2:

我误解了 IDENTITY_INSERT;我假设设置它曾经无限期地留在那张桌子上。事实上,它的存在时间与“会话”一样长,这意味着例如将其设置为迁移意味着它存在......只要迁移运行,并且与我后来的 .Add() 与 EF 的未来连接无关,这就解释了为什么我仍然得到那个异常 - 数据库确实是异常的来源,而不是 EF。由于 IDENTITY_INSERT 被限制为每个会话最多一个表,这是一种相当低效的方法 - 首先不创建 Identity PK 列似乎是一条更好的路线。

4

3 回答 3

34

这是在未启用身份自动增量的情况下创建 PK 的正确方法:

public class QuoteExtra
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int QuoteId { get; set; }
    // More fields here
}

但是,如果在 EF Migrations 已经创建表之后添加 DatabaseGenerated(DatabaseGeneratedOption.None)],它不会对表执行任何操作。如果这是您的场景,您需要添加手动迁移以删除表:

add-migration RecreateQuoteExtra

在迁移中:

public override void Up()
{
    DropTable("QuoteExtra");
}

然后,EF 自动迁移将自动重新创建没有身份约束的表,这将允许您随时设置 PK 值,而无需运行任何特殊命令,例如 IDENTITY_INSERT ON。

这听起来像 EF7(“数据运动”)中出现的破坏性较小的方法,或者如果您想避免丢失现有数据,您可以在迁移中自己编写大量手动 sql 来创建临时表并移动数据在表中。

编辑:根据您的情况,EF Migrations 可能不会重新创建表 - 如果该类已经存在并且已经添加到您的 DbContext 中,它只会删除它并保留它,这意味着您的手动迁移不仅要删除而且还要创建桌子。没什么大不了的,因为 EF Migrations 从 add-migration 为您生成的脚手架代码将为您创建这些语句,但它需要更多代码来检查问题。

于 2013-03-19T22:20:26.657 回答
4

这是正确的解决方案,但仅适用于新表。如果您更改现有表的数据库生成选项,EF 迁移将无法执行此更改,并且您的QuoteId列仍标记为Identity在数据库中。

于 2013-03-19T20:25:19.513 回答
1

我无法用您的提示解决此问题,然后我尝试重新创建整个数据库,但它也无法正常工作。

要解决此问题,您必须在第一次(!)创建列(例如 Initial-Migration)时删除identity: true属性。

也许它会帮助某人..

于 2014-03-20T14:19:03.117 回答