Chr*_*ini 20 primary-key ef-code-first ef-migrations entity-framework-5
我有一个表,为表的某些行存储一些额外的数据,如:
public class QuoteExtra
{
[Key]
public int QuoteId { get; set; }
// More fields here
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在这个表中添加行,我明确地设置了PK.
如果我只是如上所述,设置值并提交行会导致该值被丢弃并替换为数据库中自动生成的值(并且该列在实际模式中定义为Identity列).
这似乎是正确的解决方案:
public class QuoteExtra
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int QuoteId { get; set; }
// More fields here
}
Run Code Online (Sandbox Code Playgroud)
然而,这反而让我成为例外:
当IDENTITY_INSERT设置为OFF时,无法在表'EnumTest'中为标识列插入显式值.
那么,我如何编写我的类,以便我能够在EF中设置主键的值?
编辑:
我尝试添加以下基于代码的迁移将IDENTITY_INSERT设置为ON:
public override void Up()
{
Sql("SET IDENTITY_INSERT QuoteExtra ON");
}
Run Code Online (Sandbox Code Playgroud)
我跑了它并再次尝试,但得到了与上面相同的例外.奇怪的是,数据库确实反映了这个设置,并且直接运行SQL确实允许我为主键插入任意值 - 因此看起来实体框架本身正在执行此规则,而忽略了识别IDENTITY_INSERT不在事实定下来了.我需要在EF本身设置它吗?
编辑2:
我误解了IDENTITY_INSERT; 我假设将它设置为无限期地保留在该表中.实际上它只要"会话"就可以存在,这意味着例如在迁移中设置它意味着它只存在......只要迁移运行,并且与我以后的.Add()之后的未来连接没有关系. ,这解释了为什么我仍然有这个例外 - 数据库确实是异常的来源,而不是EF.由于IDENTITY_INSERT每个会话最多限制一个表,因此这是一种相当低效的方法 - 首先不创建Identity PK列似乎是一个更好的路径.
Chr*_*ini 34
这是在没有启用Identity Autoincrement的情况下创建PK的正确方法:
public class QuoteExtra
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int QuoteId { get; set; }
// More fields here
}
Run Code Online (Sandbox Code Playgroud)
但是,如果在EF迁移已经创建表之后添加DatabaseGenerated(DatabaseGeneratedOption.None)],它将对表无任何作用.如果这是您的方案,则需要添加手动迁移以删除表:
add-migration RecreateQuoteExtra
Run Code Online (Sandbox Code Playgroud)
在迁移中:
public override void Up()
{
DropTable("QuoteExtra");
}
Run Code Online (Sandbox Code Playgroud)
然后,EF自动迁移将自动重新创建没有Identity约束的表,这将允许您随时设置PK值,而无需运行任何特殊命令,如IDENTITY_INSERT ON.
这听起来像是一种破坏性较小的方式来自EF7("数据运动"),或者您可以在迁移中自己编写大量手动sql来创建临时表并移动数据,如果您想避免丢失现有数据在表中.
编辑:根据您的情况,EF迁移可能无法重新创建表 - 如果该类已经存在并且已经添加到您的DbContext中,它将丢弃它并将其保留在该表上,这意味着您的手动迁移不仅要删除,还要创建表.由于替换迁移为您生成的脚手架代码EF迁移将为您创建这些语句,但是检查问题需要更多代码.
| 归档时间: |
|
| 查看次数: |
23482 次 |
| 最近记录: |