C# 将DataAdapter.InsertCommand传递到方法会导致OleDbCommand的值为空

C# 将DataAdapter.InsertCommand传递到方法会导致OleDbCommand的值为空,c#,ms-access,ado.net,C#,Ms Access,Ado.net,我正试图从程序员天堂:C学校学习ADO.NET 这是我根据那本电子书创建的代码,但运行它会导致: System.NullReferenceException:对象引用未设置为对象的实例 尝试添加参数cmd.Parameters.add@+col时,OleDbType.Char,0,col;服从命令 有人能告诉我怎么了吗 编辑: 添加了问题描述 using System; using System.Collections.Generic; using System.Drawing; using S

我正试图从程序员天堂:C学校学习ADO.NET

这是我根据那本电子书创建的代码,但运行它会导致:

System.NullReferenceException:对象引用未设置为对象的实例

尝试添加参数cmd.Parameters.add@+col时,OleDbType.Char,0,col;服从命令

有人能告诉我怎么了吗

编辑:

添加了问题描述

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;

namespace AdoNET
{
    public partial class MainForm : Form
    {
    private OleDbConnection conn;
    private OleDbDataAdapter dataAdapter;

    private DataTable dataTable;
    private DataSet ds;

    private int currRec = 0;
    private int totalRec = 0;
    private bool insertSelected;

    public MainForm()
    {
        InitializeComponent();
    }

    void BtnLoadTableClick(object sender, EventArgs e)
    {
        this.Cursor = Cursors.WaitCursor;

        //create connection string
        string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db\\ProgrammersHeaven.mdb;";

        //create connection
        conn = new OleDbConnection(connectionString);

        //define command
        string commandString = "SELECT * FROM Article, Author WHERE Author.authorId = Article.authorId";

        //create Data Adapter for communication with DB
        dataAdapter = new OleDbDataAdapter(commandString, conn);

        //create Data Set to store data offline
        ds = new DataSet ();

        //fill dataset (table prog) with data from dataAdapter
        dataAdapter.Fill(ds, "prog");

        //create and fill table dataTable
        dataTable = ds.Tables["prog"];
        currRec = 0;
        totalRec = dataTable.Rows.Count;

        FillControls();
        InitializeCommands();
        ToggleControls(true);

        btnNext.Enabled = true;
        btnPrevious.Enabled = true;

        this.Cursor = Cursors.Default;
    }

    private void FillControls()
    {
        txtArticleID.Text = dataTable.Rows[currRec]["artId"].ToString();
        txtArticleTitle.Text = dataTable.Rows[currRec]["title"].ToString();
        txtArticleTopic.Text = dataTable.Rows[currRec]["topic"].ToString();
        txtAuthorId.Text = dataTable.Rows[currRec]["Author.authorId"].ToString();
        txtAuthorName.Text = dataTable.Rows[currRec]["name"].ToString();
        txtNumOfLines.Text = dataTable.Rows[currRec]["lines"].ToString();
        txtDateOfPublishing.Text = dataTable.Rows[currRec]["dateOfPublishing"].ToString();
    }

    void BtnNextClick(object sender, EventArgs e)
    {
        currRec++;
        if (currRec>=totalRec)
        {
            currRec=0;
        }
        FillControls();
    }

    void BtnPreviousClick(object sender, EventArgs e)
    {
        currRec--;
        if (currRec<0)
        {
            currRec=totalRec-1;
        }
        FillControls();
    }

    private void InitializeCommands()
    {
        //preparing INSERT command
        dataAdapter.InsertCommand = conn.CreateCommand();
        dataAdapter.InsertCommand.CommandText =
            "INSERT INTO article " +
            "(artId, title, topic, authorId, lines, dateOfPublishing) " +
            "VALUES (@artId, @title, @topic, @authorId, @lines, @dateOfPublishing)";
        AddParams(dataAdapter.InsertCommand, "artId", "title", "topic", "lines", "dateOfPublishing");

        //preparing UPDATE command
        dataAdapter.InsertCommand = conn.CreateCommand();
        dataAdapter.InsertCommand.CommandText =
            "UPDATE article SET" +
            "title = @title, topic = @topic, lines = @lines, dateOfPublishing = @dateOfPublishing" +
            "WHERE artId = @artId";
        AddParams(dataAdapter.UpdateCommand, "artId", "title", "topic", "authorId", "lines", "dateOfPublishing");

        //prepare DELETE command
        dataAdapter.InsertCommand = conn.CreateCommand();
        dataAdapter.InsertCommand.CommandText =
            "DELETE FROM article WHERE artId = @artId";
        AddParams(dataAdapter.DeleteCommand, "artId");
    }

    private void AddParams(OleDbCommand cmd, params string[] cols)
    {
        //adding hectic (?) parameters
        foreach (string col in cols)
        {
            cmd.Parameters.Add("@" + col, OleDbType.Char, 0, col);
        }
    }

    private void ToggleControls(bool val)
    {
        txtArticleTitle.ReadOnly = val;
        txtArticleTopic.ReadOnly = val;
        txtAuthorId.ReadOnly = val;
        txtNumOfLines.ReadOnly = val;
        txtDateOfPublishing.ReadOnly = val;

        btnLoadTable.Enabled = val;
        btnNext.Enabled = val;
        btnPrevious.Enabled = val;
        btnEditRecord.Enabled = val;
        btnInsertRecord.Enabled = val;
        btnDeleteRecord.Enabled = val;

        btnSave.Enabled = !val;
        btnCancel.Enabled = !val;
    }

    void BtnEditRecordClick(object sender, EventArgs e)
    {
        ToggleControls(false);
    }

    void BtnSaveClick(object sender, EventArgs e)
    {
        lblStatus.Text = "Saving Changes...";
        this.Cursor = Cursors.WaitCursor;
        DataRow row = dataTable.Rows[currRec];
        row.BeginEdit();
        row["title"] = txtArticleTitle.Text;
        row["topic"] = txtArticleTopic.Text;
        row["Article.authorId"] = txtAuthorId.Text;
        row["lines"] = txtNumOfLines.Text;
        row["dateOfPublishing"] = txtDateOfPublishing.Text;
        row.EndEdit();
        dataAdapter.Update(ds, "prog");
        ds.AcceptChanges();

        ToggleControls(true);
        insertSelected = false;
        this.Cursor = Cursors.Default;
        lblStatus.Text = "Changes Saved";
    }


    void BtnCancelClick(object sender, EventArgs e)
    {
        if (insertSelected)
        {
            BtnDeleteRecordClick(null,null);
            insertSelected=false;
        }

        FillControls();
        ToggleControls(true);
    }

    void BtnDeleteRecordClick(object sender, EventArgs e)
    {
        DialogResult res = MessageBox.Show("Are you sure you want to delete the current record?",
                                           "Confirm Record Deletion", MessageBoxButtons.YesNo);
        if (res == DialogResult.Yes)
        {
            DataRow row = dataTable.Rows[currRec];
            row.Delete();
            dataAdapter.Update(ds, "prog");
            ds.AcceptChanges();
            lblStatus.Text = "Record Deleted";
            totalRec--;
            currRec = totalRec - 1;
            FillControls();
        }
    }

    void BtnInsertRecordClick(object sender, EventArgs e)
    {
        insertSelected = true;
        //table must be loaded to create new row
        DataRow row = dataTable.NewRow();
        dataTable.Rows.Add(row);
        totalRec = dataTable.Rows.Count;
        currRec = totalRec-1;
        row["artId"] = totalRec;

        txtArticleID.Text = totalRec.ToString();
        txtArticleTitle.Text = "";
        txtArticleTopic.Text = "";
        txtAuthorId.Text = "";
        txtNumOfLines.Text = "";
        txtDateOfPublishing.Text = DateTime.Now.Date.ToString();

        ToggleControls(false);
    }
}

}

在InitializeCommand方法中,不创建要发送到AddParams方法中的更新和删除命令

在相应位置将dataAdapter.InsertCommand更改为dataAdapter.UpdateCommand和dataAdapter.delete命令


旁注:如果您阅读了错误消息,很明显您正在尝试使用一些引用,这些引用没有引用堆中的任何对象。在这种情况下,请运行您的代码以找到没有定义的人。

我意识到这已经晚了几年,但在查看您的代码片段后,我想添加一些内容:

private void AddParams(OleDbCommand cmd, params string[] cols)
{
    //adding hectic (?) parameters
    foreach (string col in cols)
    {
        cmd.Parameters.Add("@" + col, OleDbType.Char, 0, col);
    }
}
这是一个OleDb数据连接。我不是100%,但在使用参数名的@语法时,我从未像使用Microsoft SQL那样让参数正常工作。你可能想看看这个。如果我没有弄错的话,OleDb使用的是?符号,并忽略指定的名称。您至少必须尽我所能,按照SQL语句中声明的相同顺序添加参数,因为OleDb不会尝试匹配它们——这也是我所能做到的

此外,您正在将此OleDbTypeChar参数的大小指定为0。如果您试图为参数赋值,也可能会导致问题

因为这个答案仍然会在搜索中出现,所以我想发布一些东西,让其他好奇的人能够像我刚才一样阅读你的代码