使用ASPNET Boilerplate(.NET Framework)3.6.1
我已经成功地在许多实体上使用了AsyncCrudAppService,没有出现问题,但是我遇到了一个无法插入的特定实体类型的问题,因为Entity Framework似乎认为它已被提供了显式ID。< / p>
我的实体:
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创建方法:
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方法发送id:0。这与可以正常工作的另一个实体插入完全相同。
在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之间的差异,但找不到任何差异。甚至有一个同事来验证。
你知道这里会发生什么吗?
答案 0 :(得分:2)
您需要为实体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);
}
答案 1 :(得分:0)
我发现了这个隐患。
在我的DbContext中,我以前曾尝试为Guid字段提供一个默认值(我现在意识到,这也使它成为EF的标识列)。最后这没有用,但我忽略了整理它:
modelBuilder.Entity<Attendance>()
.Property(x => x.Guid)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
数据库在Guid列上没有任何标识列,并且错误与Id列有关,但是很显然,这使EF在结果查询中对id值的处理变得混乱。
删除了上面的代码,对其进行了重新构建,一切都可以正常工作。