You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Android应用创建训练时避免新增ExerciseType的方法

问题解决:阻止EF Core保存训练时插入已有ExerciseType

EF Core之所以尝试插入新的ExerciseType,是因为它把你关联的实例识别成了未被跟踪的新实体,而非数据库中已存在的记录。以下是几种直接有效的解决办法:


1. 显式添加外键属性(最推荐)

在ExerciseTypeGroup类中添加对应的外键字段,让EF明确知道这是关联现有ExerciseType的外键,而非需要新建的实体:

public class ExerciseTypeGroup
{
    [Key]
    public int ExerciseTypeGroupId { get; set; }
    // 新增外键字段
    public int ExerciseTypeId { get; set; }
    // 配置外键关联
    [ForeignKey(nameof(ExerciseTypeId))]
    public ExerciseType ExerciseType { get; set; }
    public List<Exercise> Exercises { get; set; }

    public ExerciseTypeGroup()
    {
        Exercises = new List<Exercise>();
    }
}

这样EF会自动通过外键关联已有ExerciseType,不会触发插入操作。


2. 确保ExerciseType被当前上下文跟踪

检查你的ExerciseTypeManager.ReadAsync方法,如果里面使用了AsNoTracking(),返回的实体是未被上下文跟踪的,EF会误判为新实体。修改方法去掉AsNoTracking():

public async Task<ExerciseType> ReadAsync(int id)
{
    // 直接用FindAsync或普通查询,不要加AsNoTracking
    return await dbContext.ExerciseTypes.FindAsync(id);
}

如果ExerciseTypeManager和WorkoutManager使用的是不同的DbContext实例,获取到的ExerciseType不在当前Workout的上下文里,需要手动附加并设置状态:

public async Task CreateAsync(Workout item)
{
    try
    {
        foreach (var group in item.ExerciseTypeGroups)
        {
            // 告诉EF这个ExerciseType是已存在的,不需要保存
            dbContext.Attach(group.ExerciseType).State = EntityState.Unchanged;
        }
        dbContext.Workouts.Add(item);
        await dbContext.SaveChangesAsync();
    }
    catch (Exception)
    {
        throw;
    }
}

3. 手动设置实体状态为Unchanged

如果上面的方法不适用,直接在保存前标记ExerciseType为未修改状态:

// 在CompleteWorkout的循环中
ExerciseType exerciseTypefromDb = await ExerciseTypeManager.ReadAsync(item.ExerciseType.ExerciseTypeId);
item.ExerciseType = exerciseTypefromDb;
// 如果是跨上下文,需要在Workout的上下文中附加并设置状态
// dbContext.Attach(exerciseTypefromDb).State = EntityState.Unchanged;

额外检查:配置实体关系

如果使用Fluent API配置DbContext,确保ExerciseType和ExerciseTypeGroup的关系正确:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ExerciseTypeGroup>()
        .HasOne(etg => etg.ExerciseType)
        .WithMany() // 如果ExerciseType没有反向导航属性,就用WithMany()
        .HasForeignKey(etg => etg.ExerciseTypeId)
        .OnDelete(DeleteBehavior.Restrict); // 根据业务需求设置删除行为
}

内容的提问来源于stack exchange,提问作者dancho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:37:40