繁体   English   中英

InsertAndGetIdAsync-无法为标识列插入显式值

[英]InsertAndGetIdAsync - Cannot insert explicit value for identity column

使用ASPNET Boilerplate(.NET Framework)3.6.1

我已经成功地在许多实体上使用了AsyncCrudAppService,没有出现问题,但是我遇到了一个我无法插入的特定实体类型的问题,因为Entity Framework似乎认为它已被提供了显式ID。

我的实体:

public class Attendance : FullAuditedEntity<int>
{
    [Required]
    public Guid Guid { get; set; }

    public long? UserId { get; set; }
    [Required]
    public int EventId { get; set; }
    public int StatusId { get; set; }

    [Required]
    [MaxLength(100)]
    public string InviteEmail { get; set; }
    [Required]
    [MaxLength(20)]
    public string InviteCode { get; set; }

    public bool InviteAccepted { get; set; }

    public DateTime? InviteAcceptedDate { get; set; }

    public string InviteSource { get; set; }
    public long? InvitedByUserId { get; set; }

    [ForeignKey("UserId")]
    public User User { get; set; }
    [ForeignKey("InvitedByUserId")]
    public User InvitedByUser { get; set; }

    [ForeignKey("EventId")]
    public Event Event { get; set; }

    [ForeignKey("StatusId")]
    public AttendanceStatus Status { get; set; }
}

我的CreateDto

[AutoMapTo(typeof(Attendance))]
public class CreateAttendanceDto
{
    public long? UserId { get; set; }
    [Required]
    public int EventId { get; set; }
    public int StatusId { get; set; }

    [Required]
    [MaxLength(100)]
    public string InviteEmail { get; set; }

    public bool InviteAccepted { get; set; }

    public DateTime? InviteAcceptedDate { get; set; }
    public string InviteSource { get; set; }
    public long? InvitedByUserId { get; set; }

}

我的AppService的Create方法:

public override async Task<AttendanceDto> Create(CreateAttendanceDto input)
    {
        var attendance = ObjectMapper.Map<Attendance>(input);

        attendance.InviteCode = "TEST";

        // Create GUID
        attendance.Guid = Guid.NewGuid();

        await _attRepository.InsertAndGetIdAsync(attendance);
        return MapToEntityDto(attendance);
    }

调试实体表明正在将id:0发送到insert方法。 这与可以正常工作的另一个实体插入完全相同。

在SQL事件探查器中跟踪两个不同的实体插入查询,我可以看到工作的对象已从插入查询中删除了ID,其中上面一个不起作用的对象正在尝试将id = 0插入数据库中,这显然是问题。

InsertAndGetIdAsync调用返回的错误如下:

错误2018-07-10 17:29:06,249 [108] nHandling.AbpApiExceptionFilterAttribute-更新条目时发生错误。 有关详细信息,请参见内部异常。 System.Data.Entity.Infrastructure.DbUpdateException:更新条目时发生错误。 有关详细信息,请参见内部异常。 ---> System.Data.Entity.Core.UpdateException:更新条目时发生错误。 有关详细信息,请参见内部异常。 ---> System.Data.SqlClient.SqlException:当IDENTITY_INSERT设置为OFF时,无法为表'Attendance'中的Identity列插入显式值。

我已经检查并仔细检查了这两个appservice Creates及其相关实体和dto之间的差异,但找不到任何差异。 甚至有一个同事来验证。

知道这里可能会发生什么吗?

您需要为实体Attendance指定一个映射,以便它不会尝试在ID列中插入值。 简而言之,您需要让EF知道ID列已配置为IDENTITY。 异常消息非常清楚地说明了这一点。

System.Data.SqlClient.SqlException:当IDENTITY_INSERT设置为OFF时,无法为表'Attendance'中的Identity列插入显式值。


使用属性:

public class Attendance {
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public long AttendanceId { get; set; }
}

或在DbContext类型的流利映射中

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
  modelBuilder.Entity<Attendance>().Property(t => t.AttendanceId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}

我发现了这个隐患。

在我的DbContext中,我以前曾尝试为Guid字段提供一个默认值(我现在意识到,这也使它成为EF的标识列)。 最后这没有用,但我忽略了整理它:

        modelBuilder.Entity<Attendance>()
            .Property(x => x.Guid)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

该数据库在Guid列上没有任何标识列,并且该错误与Id列有关,但显然,这使EF在结果查询中对id值的处理变得混乱。

删除了上面的代码,对其进行了重新构建,并且一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM