You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C#中用本地数据库创建数据集?WinForms客户数据库报错求助

C# WinForms本地数据库:修复连接错误+实现客户搜索/添加功能

嘿,作为C#初学者遇到这个连接字符串的问题太正常了,我来一步步帮你解决,顺便把客户搜索、添加的完整流程给你理清楚,保证你能看懂!

一、先搞定你的连接字符串错误

你碰到的System.ArgumentException完全是因为连接字符串的格式写错了!你把Data Source和后面的(localdb)\mssqllocaldb连在一起写了,SQL解析器根本识别不了这个“四不像”的关键字。

正确的LocalDB连接字符串应该是这样的(注意参数之间的空格和分隔):

// 用@符号避免转义反斜杠,|DataDirectory|会自动指向程序输出目录(比如bin\Debug)
string connectionString = @"Data Source=(localdb)\mssqllocaldb;AttachDbFilename=|DataDirectory|\CustomerDB.mdf;Integrated Security=True";
  • 如果你还没有创建CustomerDB.mdf文件,SQL会自动帮你生成一个;
  • 要是你已经有数据库文件,记得把它放到项目的输出目录,或者在项目里添加这个文件后,设置它的复制到输出目录为“如果较新则复制”。

二、完整实现客户搜索/添加功能(适合初学者)

我给你写了一套完整的代码,带详细注释,直接套到你的WinForms项目里就能用:

1. 先声明类级变量

在你的Form类里先定义需要用到的连接和数据表:

private DataTable TableCust; // 用来存客户数据的表
private SqlConnection cnCust; // 数据库连接对象

2. 初始化数据库和数据表

在Form的Load事件里完成初始化,包括创建表(第一次运行时)和加载现有数据:

private void Form1_Load(object sender, EventArgs e)
{
    // 初始化连接字符串
    string connectionString = @"Data Source=(localdb)\mssqllocaldb;AttachDbFilename=|DataDirectory|\CustomerDB.mdf;Integrated Security=True";
    cnCust = new SqlConnection(connectionString);
    
    // 初始化客户表并加载数据
    InitializeCustomerTable();
}

private void InitializeCustomerTable()
{
    TableCust = new DataTable("Customers");
    // 先检查数据库里有没有Customers表,没有就创建
    CreateCustomerTableIfNotExists();
    // 把数据库里的现有客户数据加载到DataTable
    LoadCustomerData();
}

private void CreateCustomerTableIfNotExists()
{
    // SQL语句:如果不存在Customers表就创建它
    string createTableSql = @"
        IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Customers')
        BEGIN
            CREATE TABLE Customers (
                Id INT PRIMARY KEY IDENTITY(1,1), -- 自增主键
                PhoneNumber NVARCHAR(20) NOT NULL UNIQUE, -- 手机号设为唯一,避免重复添加
                CustomerName NVARCHAR(50), -- 客户姓名
                Email NVARCHAR(50) -- 邮箱
                -- 你可以在这里加其他需要的字段,比如地址、生日之类的
            )
        END";
    
    // using语句会自动释放资源,不用手动关连接
    using (SqlCommand cmd = new SqlCommand(createTableSql, cnCust))
    {
        try
        {
            cnCust.Open();
            cmd.ExecuteNonQuery();
        }
        catch (Exception ex)
        {
            MessageBox.Show($"创建表失败:{ex.Message}");
        }
        finally
        {
            if (cnCust.State == ConnectionState.Open)
                cnCust.Close();
        }
    }
}

private void LoadCustomerData()
{
    // 从数据库查询所有客户数据
    string selectSql = "SELECT * FROM Customers";
    using (SqlDataAdapter adapter = new SqlDataAdapter(selectSql, cnCust))
    {
        TableCust.Clear();
        adapter.Fill(TableCust); // 把数据填充到DataTable里
    }
}

3. 实现手机号搜索功能

假设你有一个输入手机号的文本框txtPhone,一个搜索按钮btnSearch,还有显示姓名的txtName、显示邮箱的txtEmail,点击搜索按钮时执行以下代码:

private void btnSearch_Click(object sender, EventArgs e)
{
    string phoneNumber = txtPhone.Text.Trim();
    if (string.IsNullOrEmpty(phoneNumber))
    {
        MessageBox.Show("请输入手机号哦!");
        return;
    }
    
    // 在DataTable里查找匹配手机号的客户(也可以直接查数据库,这里用DataTable更高效)
    DataRow[] foundRows = TableCust.Select($"PhoneNumber = '{phoneNumber}'");
    
    if (foundRows.Length > 0)
    {
        // 找到客户,把数据填到文本框里
        txtName.Text = foundRows[0]["CustomerName"].ToString();
        txtEmail.Text = foundRows[0]["Email"].ToString();
        MessageBox.Show("找到匹配的客户啦!");
    }
    else
    {
        // 没找到,询问是否添加新客户
        DialogResult result = MessageBox.Show("没找到这个客户,要不要添加新的?", "提示", MessageBoxButtons.YesNo);
        if (result == DialogResult.Yes)
        {
            AddNewCustomer(phoneNumber);
        }
    }
}

4. 实现添加新客户功能

这个方法用来把新客户数据插入数据库,一定要用参数化查询,避免SQL注入,也防止特殊字符导致的错误:

private void AddNewCustomer(string phoneNumber)
{
    string name = txtName.Text.Trim();
    string email = txtEmail.Text.Trim();
    
    // 参数化SQL语句,用@占位符代替直接拼接字符串
    string insertSql = @"
        INSERT INTO Customers (PhoneNumber, CustomerName, Email)
        VALUES (@PhoneNumber, @CustomerName, @Email)";
    
    using (SqlCommand cmd = new SqlCommand(insertSql, cnCust))
    {
        // 给参数赋值,空值要转成DBNull.Value
        cmd.Parameters.AddWithValue("@PhoneNumber", phoneNumber);
        cmd.Parameters.AddWithValue("@CustomerName", string.IsNullOrEmpty(name) ? DBNull.Value : (object)name);
        cmd.Parameters.AddWithValue("@Email", string.IsNullOrEmpty(email) ? DBNull.Value : (object)email);
        
        try
        {
            cnCust.Open();
            int rowsAffected = cmd.ExecuteNonQuery();
            if (rowsAffected > 0)
            {
                MessageBox.Show("新客户添加成功!");
                // 刷新DataTable,把新数据加载进来
                LoadCustomerData();
                // 清空文本框,方便下次输入
                txtPhone.Clear();
                txtName.Clear();
                txtEmail.Clear();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"添加客户失败:{ex.Message}");
        }
        finally
        {
            if (cnCust.State == ConnectionState.Open)
                cnCust.Close();
        }
    }
}

三、给初学者的几个重要提醒

  • 永远用参数化查询:别直接把用户输入拼到SQL里,不然不仅容易出错,还会被SQL注入攻击;
  • 用using管理资源:SqlConnection、SqlCommand这些对象都要放在using里,它会自动帮你释放资源,不用手动操心关闭连接;
  • 检查连接状态:每次操作数据库后,确保连接是关闭的,using会帮你处理,但手动写的话一定要注意;
  • |DataDirectory|的作用:这个特殊路径会自动指向你的程序输出目录(比如bin\Debug),不用写死路径,移植性更强。

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

火山引擎 最新活动