当不尝试为IDENTITY列

时间:2016-06-09 08:00:17

标签: c# sql-server entity-framework asp.net-web-api2

我有一个使用Code First的WebApi2 / Entity Framework项目抛出了这个错误:

Cannot insert explicit value for identity column in table 'Sessions' when IDENTITY_INSERT is set to OFF.

这是模型:

public class Session
{
    [Key, ForeignKey("Device")]
    public long Id { get; set; }
    public virtual Device Device { get; set; }
}
public class Device
{
    [Key]
    public long Id { get; set; }
    public long AnalyticsId { get; set; }
    [ForeignKey("AnalyticsId")]
    public Session AnalyticsSession { get; set; }
}

控制器:

    public async Task<IHttpActionResult> PostSession(SessionInitialDTO sessionDTO)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        Session session = new Session();

        db.Sessions.Add(session);

        Analytics.Models.Device device = sessionDTO.Device;
        device.AnalyticsSession = session;

        db.Devices.Add(device);

        await db.SaveChangesAsync();

        return CreatedAtRoute("CreateInitialSession", new { id = session.Id }, session);
    }

我读过的所有内容都说这个问题来自于尝试将IDENTITY列设置为某个值,但据我所知,我并没有尝试这样做(或者至少我是我,我没有看到哪里)。 DTO中的Device对象未设置Id。我已经看到一些建议使用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]注释来指定该字段是自动生成的,但由于ForeignKey而导致问题

这是生成的表的代码:

CREATE TABLE [dbo].[Sessions] (
  [Id]           BIGINT         IDENTITY (1, 1) NOT NULL,
  CONSTRAINT [PK_dbo.Sessions] PRIMARY KEY CLUSTERED ([Id] ASC),
  CONSTRAINT [FK_dbo.Sessions_dbo.Devices_Id] FOREIGN KEY ([Id]) REFERENCES [dbo].[Devices] ([Id])
);

CREATE TABLE [dbo].[Devices] (
  [Id]                  BIGINT         IDENTITY (1, 1) NOT NULL,
  [AnalyticsId]         BIGINT         NOT NULL,
  CONSTRAINT [PK_dbo.Devices] PRIMARY KEY CLUSTERED ([Id] ASC)
);

奇怪的是,这曾经工作过,我对模型进行了一些更改,开始得到这个,恢复到这个版本的模型,并且错误仍然存​​在。

2 个答案:

答案 0 :(得分:1)

问题是Session.Id是标识列。首先创建设备记录并尝试设置会话外键 - Id。

您必须禁用身份:

public class Session
{
    [Key, ForeignKey("Device")]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long Id { get; set; }
    public virtual Device Device { get; set; }
}

答案 1 :(得分:1)

不试图了解模型是否符合要求(设备可以有一个或零个会话),您正在尝试建立1-1关系,因此Session.Id无法自动生成(默认使用EF整数键自动生成)。
要指定它,您只需将属性[DatabaseGenerated(DatabaseGeneratedOption.None)]添加到Session.Id属性即可 之后,您需要迁移数据库,因为Session.Id将不是IDENTITY。