Entity Framework中无主键ATTEMPTED_ANSWER表的关联加载问题求助
解决无主键表的EF读写问题
嘿,作为ASP.NET MVC和EF的新手,碰到无主键现有表的问题确实头疼,我来一步步帮你搞定:
1. 修正实体模型,移除不存在的Id列并配置正确映射
你之前在ATTEMPTED_ANSWER模型里加了数据库不存在的id列并标记为[Key],这就是查询时报错Invalid column name 'id'的根源。现在我们调整模型,适配无主键的数据库表:
修正后的ATTEMPTED_ANSWER模型
public class ATTEMPTED_ANSWER { // 新增非映射的Id属性,仅用于内存中标识实体 [NotMapped] public int Id { get; set; } // 配置复合主键(用现有字段的唯一组合作为EF识别的主键) [Key, Column(Order = 0)] [ForeignKey("Question")] public int question_id { get; set; } // 映射数据库的answered_option_id列,且设为可空类型 [Key, Column(Order = 1, Name = "answered_option_id")] public int? attempted_option_id { get; set; } // 映射数据库的answered_text列 [Key, Column(Order = 2, Name = "answered_text")] public string attempted_text { get; set; } public QUESTIONS Question { get; set; } }
关键说明:
[NotMapped]:告诉EF这个Id属性不需要映射到数据库列,仅在内存中使用- 复合主键:用
[Key]+Column(Order)标记现有字段组合作为EF的主键,让EF能正确跟踪实体进行读写 - 列名映射:因为模型字段名和数据库列名不一致(比如
attempted_option_id对应数据库的answered_option_id),必须用Name参数指定数据库列名,避免EF找不到列的错误
2. 可选:用Fluent API配置实体(替代DataAnnotations)
如果你更习惯用Fluent API,也可以在DbContext的OnModelCreating方法里这样配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ATTEMPTED_ANSWER>() // 设置复合主键 .HasKey(a => new { a.question_id, a.attempted_option_id, a.attempted_text }) // 映射数据库列名 .Property(a => a.attempted_option_id) .HasColumnName("answered_option_id"); modelBuilder.Entity<ATTEMPTED_ANSWER>() .Property(a => a.attempted_text) .HasColumnName("answered_text"); // 配置关联关系 modelBuilder.Entity<ATTEMPTED_ANSWER>() .HasOne(a => a.Question) .WithMany(q => q.Attempted_Answers) .HasForeignKey(a => a.question_id); }
3. 查询时自动设置Id属性
现在查询关联数据不会再报错了,接下来实现加载后自动给ATTEMPTED_ANSWER的Id赋值:
var QuestionList = _context.Questions .Where(m => m.survey_id == id) .Include(m => m.Options) .Include(m => m.Attempted_Answers) .ToList(); // 给每个ATTEMPTED_ANSWER生成唯一的内存Id int idCounter = 1; foreach (var question in QuestionList) { foreach (var answer in question.Attempted_Answers) { answer.Id = idCounter++; } }
这样每次加载数据后,所有关联的ATTEMPTED_ANSWER实体都会有一个自增的Id值,满足你的需求。
4. 读写操作注意事项
- 因为用了复合主键,更新或删除
ATTEMPTED_ANSWER时,EF会根据复合主键的字段组合定位数据库中的记录 - 如果
attempted_option_id或attempted_text为空,要确保这些值的组合在数据库中是唯一的,否则EF可能会误操作重复记录
内容的提问来源于stack exchange,提问作者Rajinder Nagi
相关产品推荐
相关产品推荐

