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

C#/.NET Windows Forms书店数据库应用开发(含事件处理)技术求助

Hey there! It sounds like you've already made solid progress on your C#/.NET WinForms bookstore assignment—let's dive into the most common bottlenecks folks hit with this kind of app, and break down practical fixes for each key feature:

C#/.NET WinForms Bookstore App: Targeted Solutions for Your Bottlenecks

1. Admin/Regular User Permission Separation (Non-Simultaneous Login)

First, let's lock down the user role system—this is usually where folks get tripped up on access control:

  • Database Setup: Add a Users table with fields like UserId, Username, PasswordHash (never store plaintext passwords!), and Role (e.g., "Admin" or "Regular"). Use BCrypt.Net-Next or System.Security.Cryptography to hash passwords during user creation.
  • Persist Role After Login: Store the authenticated user's role in a static property in your Program class, like public static string CurrentUserRole { get; set; }. This lets you access the role across all forms without passing it around manually.
  • Control UI Access: On form load, check the role and toggle control visibility/enability:
    private void MainDashboard_Load(object sender, EventArgs e)
    {
        if (Program.CurrentUserRole == "Regular")
        {
            // Hide admin-only features
            btnPurchaseInventory.Visible = false;
            btnGenerateSalesReport.Enabled = false;
        }
    }
    

2. Database-Driven Core Features

Adding Customers (Safe & Clean)

Always use parameterized queries to avoid SQL injection—here's a quick implementation for your add customer button:

private async void btnAddCustomer_Click(object sender, EventArgs e)
{
    var connectionString = @"Your_Connection_String_Here"; // Replace with your actual string
    using var conn = new SqlConnection(connectionString);
    await conn.OpenAsync();

    var query = @"INSERT INTO Customers (FullName, Email, PhoneNumber) 
                  VALUES (@FullName, @Email, @PhoneNumber)";
    using var cmd = new SqlCommand(query, conn);
    
    // Add parameters to prevent injection
    cmd.Parameters.AddWithValue("@FullName", txtCustomerName.Text.Trim());
    cmd.Parameters.AddWithValue("@Email", txtCustomerEmail.Text.Trim());
    cmd.Parameters.AddWithValue("@PhoneNumber", txtCustomerPhone.Text.Trim());

    try
    {
        await cmd.ExecuteNonQueryAsync();
        MessageBox.Show("Customer added successfully!");
        // Refresh your customer list here to show the new entry
        LoadCustomerList();
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Failed to add customer: {ex.Message}");
    }
}

Processing Sales & Inventory Purchases (Data Consistency)

The big risk here is partial updates (e.g., a sale records but stock doesn't decrease). Use database transactions to ensure all operations succeed or fail together:

private async void btnProcessSale_Click(object sender, EventArgs e)
{
    var connectionString = @"Your_Connection_String_Here";
    using var conn = new SqlConnection(connectionString);
    await conn.OpenAsync();
    using var transaction = conn.BeginTransaction();

    try
    {
        // 1. Insert sale record
        var saleQuery = @"INSERT INTO Sales (CustomerId, BookId, SaleDate, Quantity) 
                          VALUES (@CustomerId, @BookId, GETDATE(), @Quantity)";
        using var saleCmd = new SqlCommand(saleQuery, conn, transaction);
        saleCmd.Parameters.AddWithValue("@CustomerId", cboSelectedCustomer.SelectedValue);
        saleCmd.Parameters.AddWithValue("@BookId", cboSelectedBook.SelectedValue);
        saleCmd.Parameters.AddWithValue("@Quantity", numSaleQuantity.Value);
        await saleCmd.ExecuteNonQueryAsync();

        // 2. Decrease stock quantity
        var inventoryQuery = @"UPDATE Inventory 
                               SET StockQuantity = StockQuantity - @Quantity 
                               WHERE BookId = @BookId";
        using var inventoryCmd = new SqlCommand(inventoryQuery, conn, transaction);
        inventoryCmd.Parameters.AddWithValue("@Quantity", numSaleQuantity.Value);
        inventoryCmd.Parameters.AddWithValue("@BookId", cboSelectedBook.SelectedValue);
        await inventoryCmd.ExecuteNonQueryAsync();

        // Commit only if both steps work
        transaction.Commit();
        MessageBox.Show("Sale processed successfully!");
        LoadInventoryList(); // Refresh inventory to show updated stock
    }
    catch (Exception ex)
    {
        // Roll back if anything fails
        transaction.Rollback();
        MessageBox.Show($"Sale failed: {ex.Message}");
    }
}

For inventory purchases, just reverse the inventory update (add instead of subtract) and use a similar transaction flow.

3. Sales Performance Reports

WinForms gives you two solid options for reports:

  • Quick Data Grid View: Load filtered sales data into a DataGridView for on-screen viewing:
    private async void btnGenerateReport_Click(object sender, EventArgs e)
    {
        var connectionString = @"Your_Connection_String_Here";
        using var conn = new SqlConnection(connectionString);
        var query = @"SELECT c.FullName AS Customer, b.Title AS Book, s.SaleDate, s.Quantity, 
                             b.Price * s.Quantity AS TotalAmount
                      FROM Sales s
                      JOIN Customers c ON s.CustomerId = c.CustomerId
                      JOIN Books b ON s.BookId = b.BookId
                      WHERE s.SaleDate BETWEEN @StartDate AND @EndDate";
        
        using var adapter = new SqlDataAdapter(query, conn);
        adapter.SelectCommand.Parameters.AddWithValue("@StartDate", dtpReportStart.Value);
        adapter.SelectCommand.Parameters.AddWithValue("@EndDate", dtpReportEnd.Value);
        
        var reportData = new DataTable();
        adapter.Fill(reportData);
        dgvSalesReport.DataSource = reportData;
    }
    
  • RDLC Reports: For printable, formatted reports, use the Microsoft.Reporting.WinForms library. You can design a report template in Visual Studio and bind it to your sales data—great for professional-looking output.

4. Event Handling Best Practices

  • Avoid UI Freezes: Always use async/await for database operations (like the examples above) so your app stays responsive while waiting for data.
  • Refresh Data After Actions: After adding a customer, processing a sale, or updating inventory, reload your list controls (like dropdowns or data grids) to show the latest data.
  • Validate Input: Add checks for empty fields, valid email formats, or negative quantities before hitting the database—this saves you from unnecessary errors.

If you're stuck on a specific issue (like a weird error message, permission control glitches, or report formatting), share the relevant code snippets or error details, and we can narrow it down further!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:16:53