You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET C# 复合键插入及账户编辑页数据增改操作技术咨询

Hey there! Let's work through your ASP.NET C# account edit page requirement step by step. I'll cover everything from login redirection, handling insert/update across 3 tables, and solving composite key insertion issues. Here's a practical, implementation-focused approach:


1. Core Flow Overview

First, let's align on the end-to-end user journey:

  • User logs in → system validates credentials → redirect to My Account page
  • My Account page fetches and displays all user data from 3 tables
  • User edits information → submit form → system runs update/insert logic across all tables → show success message

2. Data Layer Setup (Entity Framework Core)

Assuming you're using EF Core for data access, let's define your entities and DbContext—including handling the composite key table.

2.1 Entity Classes

First, complete the Member entity (based on your truncated table definition) and define a sample composite key entity:

// Member entity (matches your SQL table structure)
public class Member
{
    public int MemberID { get; set; }
    [Required]
    [MaxLength(30)]
    public string MemberName { get; set; }
    [Required]
    public long Phone { get; set; }
    [Required]
    [EmailAddress]
    public string Email { get; set; }
    // Add any other fields from your truncated SQL definition
}

// Example composite key entity (e.g., MemberAddress where MemberID + AddressID = composite key)
public class MemberAddress
{
    public int MemberID { get; set; }
    public int AddressID { get; set; }
    [Required]
    public string AddressLine { get; set; }
    public string City { get; set; }
    // Navigation property to link back to Member
    public Member Member { get; set; }
}

// Third table entity (adjust based on your actual schema)
public class MemberPreference
{
    public int PreferenceID { get; set; }
    public int MemberID { get; set; }
    public bool ReceiveNewsletter { get; set; }
    public Member Member { get; set; }
}

2.2 DbContext Configuration

Configure keys (including composite keys) and relationships:

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<Member> Members { get; set; }
    public DbSet<MemberAddress> MemberAddresses { get; set; }
    public DbSet<MemberPreference> MemberPreferences { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Configure Member primary key (auto-incrementing IDENTITY)
        modelBuilder.Entity<Member>()
            .HasKey(m => m.MemberID);

        // Configure composite key for MemberAddress
        modelBuilder.Entity<MemberAddress>()
            .HasKey(ma => new { ma.MemberID, ma.AddressID });

        // Configure relationships (optional but recommended)
        modelBuilder.Entity<MemberAddress>()
            .HasOne(ma => ma.Member)
            .WithMany()
            .HasForeignKey(ma => ma.MemberID);

        modelBuilder.Entity<MemberPreference>()
            .HasOne(mp => mp.Member)
            .WithMany()
            .HasForeignKey(mp => mp.MemberID);
    }
}

3. Login Redirection Logic

In your AccountController, handle login validation and redirect to the My Account page:

public class AccountController : Controller
{
    private readonly AppDbContext _context;

    public AccountController(AppDbContext context)
    {
        _context = context;
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model)
    {
        if (!ModelState.IsValid) return View(model);

        // Validate user (replace with your actual password hashing/validation logic)
        var member = await _context.Members
            .FirstOrDefaultAsync(m => m.Email == model.Email && m.Phone == model.Phone);

        if (member != null)
        {
            // Store user ID in session (use ASP.NET Core Identity for production apps!)
            HttpContext.Session.SetInt32("CurrentMemberID", member.MemberID);
            return RedirectToAction("MyAccount");
        }

        ModelState.AddModelError("", "Invalid login credentials");
        return View(model);
    }
}

4. My Account Page (Display & Edit)

4.1 ViewModel for Combined Data

Create a viewmodel to hold all data needed for the edit page:

public class AccountEditViewModel
{
    public Member Member { get; set; }
    public List<MemberAddress> MemberAddresses { get; set; }
    public MemberPreference MemberPreference { get; set; }
}

4.2 Load Data for the Page

Fetch all user-related data in the MyAccount action:

[HttpGet]
public async Task<IActionResult> MyAccount()
{
    var memberId = HttpContext.Session.GetInt32("CurrentMemberID");
    if (memberId == null) return RedirectToAction("Login");

    // Fetch core member data
    var member = await _context.Members.FindAsync(memberId);
    if (member == null) return NotFound();

    // Fetch composite key data (MemberAddresses)
    var addresses = await _context.MemberAddresses
        .Where(ma => ma.MemberID == memberId)
        .ToListAsync();

    // Fetch third table data (MemberPreference)
    var preference = await _context.MemberPreferences
        .FirstOrDefaultAsync(mp => mp.MemberID == memberId) 
        ?? new MemberPreference { MemberID = memberId.Value }; // Initialize if no record exists

    var viewModel = new AccountEditViewModel
    {
        Member = member,
        MemberAddresses = addresses,
        MemberPreference = preference
    };

    return View(viewModel);
}

4.3 Razor View (Edit Form)

Build a form to let users edit all fields, including composite key records:

@model AccountEditViewModel

<h1>My Account</h1>

@if (TempData["SuccessMessage"] != null)
{
    <div class="alert alert-success">@TempData["SuccessMessage"]</div>
}

<form asp-action="MyAccount" method="post">
    <h3>Personal Information</h3>
    <div class="form-group">
        <label asp-for="Member.MemberName"></label>
        <input asp-for="Member.MemberName" class="form-control" />
        <span asp-validation-for="Member.MemberName" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Member.Phone"></label>
        <input asp-for="Member.Phone" class="form-control" />
        <span asp-validation-for="Member.Phone" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Member.Email"></label>
        <input asp-for="Member.Email" class="form-control" />
        <span asp-validation-for="Member.Email" class="text-danger"></span>
    </div>

    <h3>Addresses</h3>
    @for (int i = 0; i < Model.MemberAddresses.Count; i++)
    {
        <div class="card mb-3">
            <div class="card-body">
                <input type="hidden" asp-for="MemberAddresses[i].MemberID" />
                <input type="hidden" asp-for="MemberAddresses[i].AddressID" />
                <div class="form-group">
                    <label asp-for="MemberAddresses[i].AddressLine"></label>
                    <input asp-for="MemberAddresses[i].AddressLine" class="form-control" />
                </div>
                <div class="form-group">
                    <label asp-for="MemberAddresses[i].City"></label>
                    <input asp-for="MemberAddresses[i].City" class="form-control" />
                </div>
            </div>
        </div>
    }

    <h3>Preferences</h3>
    <div class="form-check">
        <input asp-for="MemberPreference.ReceiveNewsletter" class="form-check-input" />
        <label asp-for="MemberPreference.ReceiveNewsletter" class="form-check-label">
            Receive monthly newsletter
        </label>
    </div>

    <button type="submit" class="btn btn-primary mt-4">Save Changes</button>
</form>

5. Handle Update/Insert Logic (Including Composite Keys)

In the MyAccount POST action, process form submissions with transaction support to ensure data consistency:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> MyAccount(AccountEditViewModel model)
{
    if (!ModelState.IsValid) return View(model);

    var memberId = HttpContext.Session.GetInt32("CurrentMemberID");
    if (memberId == null) return RedirectToAction("Login");

    // Use transaction to ensure all operations succeed or fail together
    using var transaction = await _context.Database.BeginTransactionAsync();

    try
    {
        // 1. Update Member table
        var existingMember = await _context.Members.FindAsync(memberId);
        if (existingMember != null)
        {
            existingMember.MemberName = model.Member.MemberName;
            existingMember.Phone = model.Member.Phone;
            existingMember.Email = model.Member.Email;
            _context.Members.Update(existingMember);
        }

        // 2. Handle composite key table (MemberAddresses)
        foreach (var address in model.MemberAddresses)
        {
            address.MemberID = memberId.Value;
            var existingAddress = await _context.MemberAddresses
                .FirstOrDefaultAsync(ma => ma.MemberID == memberId && ma.AddressID == address.AddressID);

            if (existingAddress != null)
            {
                // Update existing address
                existingAddress.AddressLine = address.AddressLine;
                existingAddress.City = address.City;
                _context.MemberAddresses.Update(existingAddress);
            }
            else
            {
                // Insert new address (ensure composite key is unique)
                _context.MemberAddresses.Add(address);
            }
        }

        // 3. Handle third table (MemberPreference)
        var existingPreference = await _context.MemberPreferences
            .FirstOrDefaultAsync(mp => mp.MemberID == memberId);

        if (existingPreference != null)
        {
            existingPreference.ReceiveNewsletter = model.MemberPreference.ReceiveNewsletter;
            _context.MemberPreferences.Update(existingPreference);
        }
        else
        {
            _context.MemberPreferences.Add(model.MemberPreference);
        }

        // Save all changes and commit transaction
        await _context.SaveChangesAsync();
        await transaction.CommitAsync();

        TempData["SuccessMessage"] = "Your account information has been updated successfully!";
        return RedirectToAction("MyAccount");
    }
    catch (Exception ex)
    {
        await transaction.RollbackAsync();
        ModelState.AddModelError("", "An error occurred while saving your changes. Please try again.");
        // Log the exception for debugging
        return View(model);
    }
}

6. Key Tips for Composite Key Handling
  • Uniqueness Checks: Always validate if the composite key combination exists before inserting to avoid database errors. You can also add a unique constraint in SQL for extra safety.
  • Transaction Safety: Use transactions when modifying multiple tables to prevent partial updates if one operation fails.
  • Auto-Generate Partial Keys: If one part of the composite key (like AddressID) is auto-incrementing, ensure your database or EF Core is configured to handle that correctly.

内容的提问来源于stack exchange,提问作者Reina23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:18:59