c# - ASP .NET 一对一关系 CRUD

标签 c# asp.net entity-framework

基于代码优先类 UserProfile 使用 Controller 自动生成的编辑操作存在问题。

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; }
    }

UserProfile 与类 Address 是一对一的关系。

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 不会更改 Address 表中的条目,而是尝试添加具有相同 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错误信息:

An unhandled exception occurred while processing the request.

SqlException: Cannot insert duplicate key row in object 'dbo.Address' with unique index 'IX_Address_UserProfileForeignKey'.

The duplicate key value is (9872561e-dad4-4169-9faf-154c7dcd925f). The statement has been terminated.

System.Data.SqlClient.SqlCommand+<>c.b__108_0(Task result) DbUpdateException: An error occurred while updating the entries. See the inner exception for details.

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

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

最佳答案

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

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

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

关于c# - ASP .NET 一对一关系 CRUD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48401646/

相关文章:

c# - 按通用值对字典排序

c# - 在 C# (.NET) 中是否有任何函数可以相应地比较字符串的长度?

c# - VS2013中选择 "debug"或 "release"方案配置有什么区别?

c# - HTML Firefox 表格对齐问题

c# - 将 DbContext.SaveChanges 异常记录到 Entity Framework/Entity Framework Core 中的数据库

c# - MVC 5 和 Unity IoC 中的 AccountController

c# - 始终获取依赖属性的 PropertyChangedCallback - Silverlight

c# - 无法访问没有主键的 Entity Framework 表

asp.net - 是否可以在不丢失用户 session 的情况下回收 IIS 应用程序池?

c# - 如何在自动生成的 Edmx 文件中设置 Entity Framework CommandTimeout