繁体   English   中英

EF Core - 在不加载实体的情况下修改关系

[英]EF Core - Modify realations without loading entity

我试图实现一个 function 让用户喜欢评论。 如果用户已经点赞,则不能再点赞,反之亦然。 这是它的样子:

    public async Task<ActionResult<CommentResponse>> LikeComment(LikeComment like)
    {
        if (like.HasNullProperty())
            return BadRequest("Missing properties!");
        var comment = await commentService.GetCommentWithLikes((int) like.CommentId);
        if(comment is null)
            return NotFound($"No comment with id {like.CommentId} was found");
        try
        {
            var userId = User.GetUserID();
            comment = await commentService.LikeComment(comment, userId, (bool)like.Liked);
            return comment is not null ? Ok(comment.GetCommentResponse((bool)like.Liked)) : StatusCode(304);
        }
        catch(Exception e)
        {
            return StatusCode(500, $"Error while trying to {((bool)like.Liked ? "like" : "dislike")} comment");
        }
    }

相关功能:

    public async Task<Comment> GetCommentWithLikes(int id) => await blogContext.Comments.IncludeLikes().FirstOrDefaultAsync(x => x.Id == id);
    public static IQueryable<Comment> IncludeLikes(this IQueryable<Comment> source)
        => source.Select(x => new Comment
        {
            Id = x.Id,
            ArticleId = x.ArticleId,
            CreatedById = x.CreatedById,
            CreatedAt = x.CreatedAt, 
            Likes = x.LikedBy.Count,
            Text = x.Text,
        });

和主要的逻辑:

    public async Task<Comment> LikeComment(Comment comment, string userId, bool liked)
    {
        var user = new User { Id = userId };
        var hasLiked = await blogContext.Comments.Where(x => x.Id == comment.Id && x.LikedBy.Any(x => x.Id == user.Id)).FirstOrDefaultAsync() is not null;
        Action action = null;
        if (!hasLiked && liked)
        {
            action = () => comment.LikedBy.Add(user);
            comment.LikedBy = new List<User>();
            comment.Likes++;
        }
        else if (hasLiked && !liked)
        {
            action = () => comment.LikedBy.Remove(user);
            comment.LikedBy = new List<User> { user };
            comment.Likes--;
        }
        if (action is null)
            return null;
        blogContext.Attach(user);
        blogContext.Attach(comment);
        action();
        await blogContext.SaveChangesAsync();
        return comment;
    }

这个想法是不加载整个 likeBy 关系,但仍通知 EF Core 我添加或删除了一个用户。 因此我修改了评论,然后附加它,以便 EF Core 跟踪对 likeBy 关系的更改。 有趣的是,喜欢评论时效果很好。 但是,当不喜欢时,我会收到一条评论已附加的错误消息。 在 GetCommentsWithLikes function 中使用.AsNoTracking() 没有帮助。

无法跟踪实体类型“评论”的实例,因为已经在跟踪另一个具有相同 {'Id'} 键值的实例。 附加现有实体时,请确保仅附加一个具有给定键值的实体实例。 考虑使用“DbContextOptionsBuilder.EnableSensitiveDataLogging”来查看冲突的键值。

这是链接(有效)时传递给 like func 的注释: 在此处输入图像描述

这是不喜欢的时候(只有差异是喜欢计数......): 在此处输入图像描述

这就是在失败的附加之前: 在此处输入图像描述

也许有人知道这种行为的原因,可以帮助我或提出不同的方法:) 谢谢

在 GetCommentsWithLikes function 中使用.AsNoTracking() 没有帮助

由于使用了投影,function 已经隐式没有跟踪。 这是以下调用

var hasLiked = await blogContext.Comments
    .Where(x => x.Id == comment.Id && x.LikedBy.Any(x => x.Id == user.Id))
    .FirstOrDefaultAsync() is not null;

当结果不是 null 时,将向更改跟踪器添加Comment实例。

由于您不需要该实例并且只是检查是否存在,因此请改用以下不涉及实体实例,而是纯粹的服务器端查询:

var hasLiked = await blogContext.Comments
    .AnyAsync(x => x.Id == comment.Id && x.LikedBy.Any(x => x.Id == user.Id));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM