我有以下型号:
[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已设置,导航属性对象为
非空
):
Microsoft.EntityFrameworkCore.DbUpdateException:发生错误
在更新条目时。有关详细信息,请参见内部异常。--->
约束失败'
如何防止重新插入已存在的导航属性?
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存储为
二进制数据
:
所以,当试图将二进制数据转换为文本时,实体框架核心可能有点混乱?还是不知道为什么取回能正常工作。