上传视频时出现错误:

SqlException:违反主键约束‘pk_user’.无法在对象‘dbo.User’中插入重复的键.重复密钥值为(831769c6-fc01-4203-a345-0aa12702b95e)

这是我的代码:

public async Task<IActionResult> Upload(VideoUploadViewModel model)
{
    if (ModelState.IsValid)
    {
        var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
        var user = await _userRepository.GetUserByIdAsync(userId);

        var video = new Video
        {
            Title = model.Title,
            Description = model.Description,
            DurationSeconds = model.DurationSeconds,
            CategoryId = model.CategoryId,
            User = user,
            UserId = userId
        };

        await _videoRepository.AddVideoAsync(video, model.VideoFile);

        return RedirectToAction("Index");
    }

    var categories = await _categoryRepository.GetAllCategoriesAsync();
    ViewBag.Categories = categories;

    return View(model);
}


public async Task AddVideoAsync(Video video, IFormFile videoFile)
{
    try
    {
        if (videoFile != null && videoFile.Length > 0)
        {
            var fileName = Guid.NewGuid().ToString() + Path.GetExtension(videoFile.FileName);
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "videos", fileName);

            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await videoFile.CopyToAsync(stream);
            }

            video.FilePath = fileName;
        }

        _context.Videos.Add(video);
        await _context.SaveChangesAsync();
    }
    catch (Exception)
    {
        if (!string.IsNullOrEmpty(video.FilePath))
        {
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "videos", video.FilePath);

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
        }
        throw;
    }
}
public class Video
{
    [Key]
    public int VideoId { get; set; }

    [Required(ErrorMessage = "Поле 'Название видео' обязательно для заполнения")]
    [Display(Name = "Название видео")]
    [StringLength(100, ErrorMessage = "Длина 'Названия' не должна превышать 100 символов")]
    public string Title { get; set; }

    [Required(ErrorMessage = "Поле 'Описание видео' обязательно для заполнения")]
    [Display(Name = "Описание видео")]
    [StringLength(500, ErrorMessage = "Длина 'Описания' не должна превышать 500 символов")]
    public string Description { get; set; }

    [Required(ErrorMessage = "Поле 'Продолжительность видео' обязательно для заполнения")]
    [Display(Name = "Продолжительность видео")]
    [Range(0, int.MaxValue, ErrorMessage = "Значение 'Продолжительность' должно быть неотрицательным")]
    public int DurationSeconds { get; set; }

    [ScaffoldColumn(false)]
    public string FilePath { get; set; }

    [NotMapped]
    [Display(Name = "Файл видео")]
    [Required(ErrorMessage = "Выберите видеофайл")]
    public IFormFile VideoFile { get; set; }

    [ScaffoldColumn(false)]
    public DateTime UploadDate { get; set; }

    [Display(Name = "Категория видео")]
    [Required(ErrorMessage = "Поле 'Категория видео' обязательно для заполнения")]
    public int CategoryId { get; set; }
    [ForeignKey("CategoryId")]
    public Category Category { get; set; }

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

    public ICollection<Comment> Comments { get; set; }
    public ICollection<Like> Likes { get; set; }
    public ICollection<View> Views { get; set; }

    public Video()
    {
        UploadDate = DateTime.UtcNow;
        Comments = new List<Comment>();
        Likes = new List<Like>();
        Views = new List<View>();
    }
}
public class User : IdentityUser
{
    [Key]
    public override string Id { get; set; }

    [Required(ErrorMessage = "Поле 'Email' обязательно для заполнения")]
    [EmailAddress(ErrorMessage = "Некорректный формат 'Email'")]
    public override string Email { get; set; }

    [Required(ErrorMessage = "Поле 'Логин' обязательно для заполнения")]
    [StringLength(50, MinimumLength = 3, ErrorMessage = "Длина 'Логина' должна быть от 3 до 50 символов")]
    public override string UserName { get; set; }

    [ScaffoldColumn(false)]
    [Display(Name = "Дата регистрации")]
    public DateTime RegistrationDate { get; set; }

    public ICollection<Video> Videos { get; set; }
    public ICollection<SearchHistory> SearchHistory { get; set; }
    public ICollection<WatchHistory> WatchHistory { get; set; }
    public ICollection<WatchLater> WatchLaterList { get; set; }
    public ICollection<Notification> Notifications { get; set; }
    public ICollection<View> Views { get; set; }
    public ICollection<Comment> Comments { get; set; }
    public ICollection<Like> Likes { get; set; }

    public User()
    {
        RegistrationDate = DateTime.UtcNow;
        Videos = new List<Video>();
        SearchHistory = new List<SearchHistory>();
        WatchHistory = new List<WatchHistory>();
        WatchLaterList = new List<WatchLater>();
        Notifications = new List<Notification>();
        Views = new List<View>();
        Comments = new List<Comment>();
        Likes = new List<Like>();
    }
}
public class UserRepository : IUserRepository
{
    private readonly UserManager<User> _userManager;

    public UserRepository(UserManager<User> userManager)
    {
        _userManager = userManager;
    }

    public async Task<User> GetUserByIdAsync(string id)
    {
        return await _userManager.FindByIdAsync(id);
    }
}

如果不将用户传递给模型,则视频将具有USER=NULL属性.如果您传递它,则出于某种原因,它会try 使用我传递的用户的数据创建一个新用户

推荐答案

可能最简单的 Select 是跳过对User属性的赋值(赋值UserId应该足以将Video实体以正确的状态保存到数据库):

var video = new Video
{
    Title = model.Title,
    Description = model.Description,
    DurationSeconds = model.DurationSeconds,
    CategoryId = model.CategoryId,
    // User = user,
    UserId = userId
};

看起来GetUserByIdAsync要么使用另一个上下文实例,要么执行non-tracking query.

您可以研究的另一个选项是:

  • 手动将用户对象实例Attaching到上下文(例如在AddVideoAsync调用中)
  • 修复GetUserByIdAsync,使其使用相同的上下文实例并对其执行跟踪查询(如果没有看到完整的代码,就很难知道如何实现)

Csharp相关问答推荐

如果第一个匹配项为空,则规则运算不会拆分C#中分离字符串上的子菜单

将C#字符串转换为其UTF8编码字符的十六进制表示

在命令行中使用时安装,但在单击时不会安装

获取ASP.NET核心身份认证cookie名称

如何使用C#和Graph API从Azure Directory获取用户详细信息

C#自定义字典与JSON(de—)serialize

使用两个不同的枚举作为Switch语句中的CASE生成唯一值

如何在C#中使用Postman中的本地IP向本地主机上运行的本地API发出请求

未在数据流块之间传播完成

.NET:从XPath定位原始XML文档中的 node

正在寻找新的.NET8 Blazor Web应用程序.如何将.js添加到.razor页面?

如果是,我怎么才能让这个加75,如果不是,我怎么才能减go 100?

如何防止Visual Studio断点以红色突出显示到整行?

同一组件的多个实例触发相同的事件处理程序

在.NET Maui中,Flyoutindow/Hamburger菜单可以在shell 之外实现吗?

根据优先级整理合同列表

NETSDK1201:对于面向.NET 8.0和更高版本的项目,默认情况下,指定RUNTIME标识符将不再生成自包含的应用程序

如何更改Datagridview行标题

如何对构建在Clean架构和CQRS之上的控制器进行单元测试?

如何使用moq和xUnit对删除操作进行单元测试?