如何自动增加除Id以外的Key

时间:2014-08-26 19:38:57

标签: sql-server entity-framework

我正在使用EF Code First,并且有一个没有名为Id的密钥的表。对于此表,命名Key SelectorId是有意义的。问题是,当我添加新行时,我收到错误:

  

无法将值NULL插入“SelectorId”列表中   'dbProgramData.dbo.Selectors';列不允许空值。   INSERT失败。声明已经终止。

当然它不允许空值 - 它是该表的主键,但我假设Key是自动增量。我的模型定义如下:

public class Selector
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int SelectorId { get; set; }

    public string ProgramId { get; set; }

    ....

}

我正在尝试使用此代码添加一行(在我的本地PC上使用VS工作正常,但在发布后在远程VPS上出现上述错误失败:

ProgramDbContext dbProgramData = new ProgramDbContext();

Selector selector = new Selector();

selector.ProgramId = programId;

dbProgramData.Selectors.Add(selector)
dbProgramData.SaveChanges();

在ProgramDbContext类中,我有:

public DbSet<Selector> Selectors { get; set; }

如果我要将SelectorId重命名为Id,我怀疑此问题已得到解决?运行“添加迁移”后,向上/向下脚本显示:

CreateTable(
    "dbo.Selectors",
    c => new
        {
            SelectorId = c.Int(nullable: false, identity: true),
            ProgramId = c.String(),

    ....

谁能告诉我我做错了什么?我在创建的两个表中遇到了同样的问题,并且它们都有一个名为Id以外的Pk。

更新

正如所建议的那样,我在远程服务器上进入了该表的SSMS和Design View。我看到Is Identity设置为否。我仔细检查了我的本地数据库表,Is Identity设置为是,因为它应该是。

通过右键单击数据库,然后在Tasks - &gt;上,我将数据库表提供给远程VPS服务器的方式是使用SSMS。导入数据。我指向我的本地。\ SQLEXPRESS并执行导入。似乎导入成功,但显然不是。在执行导入之前,我将删除远程数据库中的所有表。

此方法不应该创建精确的模式以及导入数据吗?

2 个答案:

答案 0 :(得分:1)

说清楚:

  • EF使用独立于物理数据库的模式定义(实体数据模型,又称EDM)
  • 数据库有自己的架构,独立于EDM

要使事情顺利进行,两个模式必须一致。因此,如果数据库中有标识列,则必须在EDM中正确定义该列。正如您所说,EDM列必须具有DatabaseGenerated属性等于DatabaseGeneratedOption.Identity。

在您的开发机器中,我不知道您是使用数据库优先或代码优先,还是绘制EDM架构来生成数据库,但很清楚架构是否一致与数据库,所以它工作正常。

如果您尝试使用的EDM示意图并不是数据库,那么您将会遇到错误。

这是标识列的工作方式:

  • 在SQL Server中,当您将identity属性添加到表的列时,当您插入新行时,您无法指定该列的值:SQL Server会自动生成序列号,并插入该行。
  • 如果EDM有一个标记为DatabaseGenerated的列,当您使用它来插入新行时,生成的SQL:
    • 不包含插入语句中的列
    • 在插入后立即选择scope_identity()函数以获取服务器生成的值。

因此,如果EDM和Databasedoesn具有一致的信息,则插入失败,这是正常的。

在这种情况下,问题显然是部署问题。您可以尝试其他方法:

  • 备份开发计算机中的数据库,并在VPS SQL Server中恢复它
  • 使用SSMS查找数据库的文件(查看数据库属性。一旦知道文件的位置,分离数据库(在SSMS中,右键单击数据库,您将在“任务”菜单选项下找到此选项)分离VPS中的数据库(如果存在)。现在,您可以将文件从开发机器复制到服务器,然后在开发机器和服务器中再次附加。

这两种方法完全是故障安全的。如果您使用导入/导出或任何其他操作来复制数据库,则可能会遇到麻烦,因为有一些选项需要配置。

顺便说一下,如果您使用的是EF Code First,除非您使用属性对其进行修改,否则默认情况下,任何整数类型的IdTableNameId都会被视为{{1列。 (按惯例,这是配置)。但是,如果您不遵循惯例,则始终可以使用属性(或Fluent API)配置列,将其标记为DatabaseGenerated并指定其生成位置。

答案 1 :(得分:0)

在sql server中,转到有问题的表的设计视图。单击要增加的列,然后在列属性面板中,向下滚动到“标识规范”。将其设置为yes,然后您应该能够将其设置为自动递增1。