我有以下模型:
[Table("Facts")]
public partial class Facts
{
[Key]
public Guid ID { get; set; }
public Guid UserID { get; set; }
[ForeignKey(nameof(UserID))]
public Users Users { get; set; }
//other properties are ommitted
}
其迁移代码:
migrationBuilder.CreateTable(
name: "Facts",
columns: table => new
{
ID = table.Column<Guid>(nullable: false),
UserID = table.Column<Guid>(nullable: false),
//other properties are ommitted
},
constraints: table =>
{
table.PrimaryKey("PK_Facts", x => x.ID);
table.ForeignKey(
name: "FK_Facts_Users_UserID",
column: x => x.UserID,
principalTable: "Users",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});
由于它具有导航属性,因此我将其设置为现有 ID(这是必需的)。
这是保存方法:
public async Task SaveData<T>(List<T> data, bool isNew) where T : class
{
if (data == null)
throw new ArgumentNullException(nameof(data));
try
{
if (isNew)
context.Set<T>().AddRange(data);
else
{
context.Set<T>().AttachRange(data);
data.ForEach(d => (context as DbContext).Entry(d).State = EntityState.Modified);
}
await context.SaveChangesAsync();
}
catch (Exception ex)
{
throw;
}
}
当我进入save方法时,我有如下状态(设置了ID,导航属性对象为null):
之后AddRange
,我有以下状态(设置了ID,导航属性对象不为null):
在 catch 中,我得到以下异常:
Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> Microsoft.Data.Sqlite.SqliteException:SQLite 错误 19:'FOREIGN KEY 约束失败'
看起来它试图将导航属性对象作为新项目添加到数据库中。
如何防止重新插入已经存在的导航属性?
更新
启用 SQL 日志记录后,我得到以下信息(@p0 是 PK,@p18 是 FK):
Failed executing DbCommand (105ms) [Parameters=[@p0='84ddca86-3f8a-41f1-aaed-2c65bd1cb384' (DbType = String),...@p18='e33f7939-bc35-4d82-b68b-e1cc0cf32ff1' (DbType = String)...]
INSERT INTO "Facts" ("ID", ... "UserID",...)
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29);
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 19: 'FOREIGN KEY constraint failed'.
更新2
我做了一些模拟器测试,我发现了以下内容。
表的数据Users
最初是通过 SQL 脚本插入的,代码如下:
public async virtual Task ExecuteCommandAsync(string sqlCommand)
{
await context.Database.ExecuteSqlCommandAsync(new RawSqlString(sqlCommand));
}
如您所见,记录存在:
当我用 保存不相关的数据时SaveData
,其 ID 存储为二进制数据:
那么,在尝试将二进制数据转换为文本时,Entity Framework Core 可能会感到困惑吗?仍然不知道为什么检索正常工作。