【问题标题】:ASP .NET One-to-One Relationship CRUDASP .NET 一对一关系 CRUD
【发布时间】:2018-01-23 12:22:21
【问题描述】:

控制器根据代码优先类UserProfile自动生成的编辑操作存在问题。

public class UserProfile : ApplicationUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
        public string ProfilePhoto { get; set; }
        public string Interests { get; set; }
        public string AboutMe { get; set; }

        public Address Address { get; set; }
        public List<Post> Posts { get; set; }
        public List<Friends> Friends { get; set; }
        public List<Messages> Messages { get; set; }
        public List<UsersGallery> UsersGallery { get; set; }
    }

UserProfileAddress 类是一对一的关系。

public class Address
    {
        [Key]
        public string AddressId { get; set; }

        public string City { get; set; }
        public string Street { get; set; }
        public string HouseOrFlatNumber { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }

        public string UserProfileForeignKey { get; set; }
        public UserProfile UserProfile { get; set; }
    }

FluentApi 中描述的关系如下:

protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<UserProfile>()
            .HasOne(p => p.Address)
            .WithOne(i => i.UserProfile)
            .HasForeignKey<Address>(b => b.UserProfileForeignKey);
        }

UserProfile 和 Address 实体在 Register 操作中创建

public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                var user = new UserProfile { UserName = model.FirstName, Email = model.Email, FirstName = model.FirstName, LastName = model.LastName, Address = new Address() };
                var result = await _userManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User created a new account with password.");

                    var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                    var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
                    await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);

                    await _signInManager.SignInAsync(user, isPersistent: false);
                    _logger.LogInformation("User created a new account with password.");
                    return RedirectToLocal(returnUrl);
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

此时我在与 UserProfileForeignKey 相关的数据库表中有适当的条目。 - 用户配置文件表 the UserProfile table - 地址表 the Address table

这里出现了一个问题。根据 sql 错误消息,自动生成的 CRUD 操作 Edit 而不是更改地址表中的条目,而是尝试添加具有相同 UserProfileForeignKey 的新条目。

我理解正确吗?为什么会这样?如何才能使“编辑”操作按应有的方式工作?

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(string id, [Bind("FirstName,LastName,BirthDate,ProfilePhoto,Interests,AboutMe,Address,Id,UserName,NormalizedUserName,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,ConcurrencyStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount")] UserProfile userProfile)
        {
            if (id != userProfile.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(userProfile);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!UserProfileExists(userProfile.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(userProfile);
        }

这里是sql错误信息:

处理请求时发生未处理的异常。

SqlException:无法在对象“dbo.Address”中插入重复的键行 具有唯一索引“IX_Address_UserProfileForeignKey”。

重复键值为 (9872561e-dad4-4169-9faf-154c7dcd925f)。声明已终止。

System.Data.SqlClient.SqlCommand+c.b__108_0(任务 结果)DbUpdateException:更新时发生错误 条目。有关详细信息,请参阅内部异常。

Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch+d__32.MoveNext()

它说 ForeignKey 9872561e-dad4-4169-9faf-154c7dcd925f 试图被复制但是为什么如果它是更新而不是插入呢?

【问题讨论】:

  • 设置子实体状态(地址),如 Aman 所示或将其提取到跟踪中(然后将更改映射回来)。
  • 谢谢,但您能建议更多细节吗?附件应该是什么样子?应该放在哪里?

标签: c# asp.net entity-framework


【解决方案1】:

这是因为你的 UserProfile 实体是分离的(实体框架没有跟踪它),所以它设置 entity.State == 在这里添加。 要附加您的实体,请参阅How to Update Existing Disconnected Entity

2018 年 1 月 27 日编辑 我试图复制您的场景并在 GitHub https://github.com/updateaman/EF6-Test 中创建了一个项目

Address 对象中设置/传递UserProfileForeignKey 属性后,我能够摆脱这个错误

【讨论】:

  • 我试过这样:_context.Address.Attach(userProfile.Address);`_context.Entry(userProfile).State = EntityState.Modified;`await _context.SaveChangesAsync(); 和这样:_context.UserProfile.Attach(userProfile); _context.Entry(userProfile).State = EntityState.Modified;await _context.SaveChangesAsync(); 仍然是相同的 sql 错误复制
  • 我看到您传递的是 userProfile 的 Id,而不是 Address 的 addressId,请传递/设置 addressId 并重试
  • 谢谢您,非常感谢您的帮助。如果您的意思是绑定,我已经与 AddressId 一起尝试过,但它不起作用。 public async Task&lt;IActionResult&gt; Edit(string id, [Bind("FirstName,LastName,BirthDate,ProfilePhoto,Interests,AboutMe,Address.AddressId,Address.City,Address.Street,Address.HouseOrFlatNumber,Address.PostalCode,Address.Country,Id,UserName,NormalizedUserName,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,ConcurrencyStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount")] UserProfile userProfile)
  • 但是错误消息发生了变化:___ DbUpdateConcurrencyException:数据库操作预计会影响 1 行,但实际上影响了 0 行。自加载实体以来,数据可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅 go.microsoft.com/fwlink/?LinkId=527962
  • 好。请求中有任何 AddressId 吗?您在 userProfile.Address.AddressId 中看到任何值吗?
猜你喜欢
  • 1970-01-01
  • 2016-02-26
  • 2021-05-27
  • 1970-01-01
  • 2021-09-15
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
相关资源
最近更新 更多