代码改变世界

EF 外键问题

  stoneniqiu  阅读(2351)  评论(1编辑  收藏  举报

    在做一个评论功能的时候,发现用户的id不对,打开数据库一看,莫名其妙的新增了几个用户。明显是将外键中的用户新增到用户表中了。

   

   评论表:

   

   

复制代码
public class CourseComment : BaseModel
    {
        public string Content { get; set; }

        [ForeignKey("UserId")]
        public virtual User FormUser { get; set; }

        public virtual int UserId { get; set; }

        public virtual CourseComment ReplayComment { get; set; }

        /// <summary>
        /// 父组
        /// </summary>
        public int CourseId { get; set; }

        [Required]
        [ForeignKey("CourseId")]
        public virtual Course Course { get; set; }

    }
复制代码

 

复制代码
    var user = GetUserById(id);
    var com = new CourseComent() { Content = comment, CourseId = id, FormUser = user };
    _comRepository.Add(com);

//add
public bool Add(CourseComent comment) { if (comment == null || string.IsNullOrEmpty(comment.Content)) return false; _db.CourseComents.Add(comment); _db.SaveChanges(); return true; }
复制代码

而原因就是user和comment不是在一个上下文中。 修改一下add方法:

复制代码
 public bool Add(CourseComent comment)
        {
            if (comment == null || string.IsNullOrEmpty(comment.Content)) return false;

            var u = _db.Users.Find(comment.FormUser.Id);
             comment.FormUser = u;
             _db.CourseComents.Add(comment);
            _db.SaveChanges();
            return true;
        }
复制代码

这个时候添加 就不会出现新增了。我们也可以看到两个对象的哈希值是不一样的。

我曾试图重写对象的对比方法和GetHashGode方法,让这两个值一样只要是id相同的话。但EF还是不识别,不知道它判断的对象的方法是什么。在有外键的操作中,一定要保持在同一个上下文中,也是同一个db对象下。

但是,上面的写法让人不舒服,要取出来再赋值一次,其实只用赋值Id就行了。

model.UserId = GetCurrentUser().Id;

另外,一个对象有两个以上的外键的时候,会报错,这个时候要取消级联删除。保留一个外键级联删除就行。

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>().HasMany(t => t.Notes).WithRequired(p => p.User).WillCascadeOnDelete(false);
            
            base.OnModelCreating(modelBuilder);
        }

 

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示