问题  无法转换三层架构中的对象类型

安德鲁·马努亚

知名会员
已加入
五月30,2019
留言内容
75
编程经验
Beginner
大家好,
我正在尝试实现从数据网格视图到数据库表的更新数据记录。
我实现了三个层,需要使用数据库表中的数据表来更新对数据网格视图数据的更改。
在我的数据访问层中,相应的代码如下所示;
C#:
 public int Update(string textFirstName, string textLastName, int textAge)
        {
            var returnValue = 0;

            using (SqlConnection conn = new SqlConnection(_connStr))

            {
                using (var dCmd = new SqlCommand(@"UPDATE tbl_Persons SET LastName = @aLastName, Age = @aAge
                                                            WHERE FirstName = @aFirstName", conn))     
                
                using (var adapter = new SqlDataAdapter { UpdateCommand = dCmd })

                {
                    conn.Open();
                    SqlParameter[] prms = new SqlParameter[3];
                    prms[0] = new SqlParameter("@FirstName", SqlDbType.VarChar, 50);
                    prms[0].Value = textFirstName;
                    prms[1] = new SqlParameter("@LastName", SqlDbType.VarChar, 50);
                    prms[1].Value = textLastName;
                    prms[2] = new SqlParameter("@Age", SqlDbType.Int);
                    prms[2].Value = textAge;

                    dCmd.Parameters.AddRange(prms);

                    returnValue = dCmd.ExecuteNonQuery();
                    dCmd.Parameters.Clear();

                    adapter.Update(table);
                }

                foreach (DataRow row in table.Rows)
                {
                    if (row["Select Item"] as bool? == true)
                    {
                        table.AcceptChanges();
                        row.SetAdded();
                    }
                }
            }
            return returnValue;
        }

我的业务层逻辑如下所示;
C#:
public int Update(string textFirstName, string textLastName, int textAge)
        {           
            return new PersonDAL().Update(textFirstName, textLastName, textAge);
        }

最后,我的表示层各自的数据更新按钮事件如下所示;
C#:
var result = 0;
            try
            {               
                result = new PersonBAL().Update(textFirstName.ToString(), textLastName.ToString(), Convert.ToInt32(textAge));
              
                if (result > 0)
                {
                    MessageBox.Show("Record updated successfully !");
                }
                else
                {
                    MessageBox.Show("No record Identified.");
                }
            }
            catch (Exception ee)
            {
                MessageBox.Show("Error occured. " + ee.Message);
            }

我已成功在表单加载事件中将数据加载到dataGridView中。

但是,在运行程序时,出现错误,"无法将类型为“ System.Windows.Forms.DataGridViewTextBoxColumn”的对象转换为类型为“ System.Iconvertible”的对象。

感谢您提供反馈意见以解决问题。

亲切的问候,

安德鲁
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,524
地点
悉尼,澳大利亚
编程经验
10+
引发异常的是哪一行?发布代码段时,代码编辑器允许您指定一个或多个行号以突出显示,这使识别代码中问题行的位置更加容易。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,524
地点
悉尼,澳大利亚
编程经验
10+
Based on the error message, I would assume that the issue is in Convert.ToInt32(textAge). That seems to suggest that textAge 是网格中的一列,而不是网格中一行中单元格的值。想必 textFirstNametextLastName 在同一条船上。如果要这样做,则需要遍历网格的各行,获取每一行的相关数据并保存该数据。您不能只获取列并期望神奇地提取数据,尤其是考虑到列实际上不包含任何数据。就像在数据库表中一样,列描述的是数据(类型,格式等),而实际上却是包含数据的行。更具体地说,在这种情况下,行包含单元格,而单元格包含数据。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
我已成功在表单加载事件中将数据加载到dataGridView中。
这是一个糟糕的主意,如果您需要提出问题的原因;你已经遇到麻烦了。除此之外,您的SQL看起来很时髦,并且您的数据库设计看起来很糟糕。我怎么这么说
C#:
 public int Update(string textFirstName, string textLastName, int textAge)
如果仅更新姓氏而不是两个名称,并且仅当姓氏满足where子句的条件时,传递名字和姓氏又有什么意义呢?
C#:
using (var dCmd = new SqlCommand(@"UPDATE tbl_Persons SET LastName = @aLastName, Age = @aAge
                                                            WHERE FirstName = @aFirstName", conn))

如果有很多姓相同的人怎么办?您应该多考虑一下。

I hope your plan isn't to then update the first name with the last name. It would be better if you would explain what you're trying to do here. Also, why is your public int not public void?

You're performing an update statement, so you shouldn't be returning anything. Least not : returnValue = dCmd.ExecuteNonQuery();. And where exactly are you handling errors when the statement fails to update?

对我来说似乎是一个坏榜样。
 
Last edited:

安德鲁·马努亚

知名会员
已加入
五月30,2019
留言内容
75
编程经验
Beginner
嗨道林斯,

我知道这不是一个好的数据库设计。我的目标不是在此阶段进行良好的数据库设计,我想了解CRUD操作在3层体系结构中的工作方式,并且如果我正确理解了编程概念,则希望迁移使用单层到三层体系结构。

因此,"btn_Update"事件代码如下所示(我添加了一个名为"PersonID" to my database.;
C#:
  var result = 0;
            try
            {               
                int age = 0;
                int.TryParse(txtAge.Text, out age);

                int personID = 0;
                int.TryParse(txtPersonID.Text, out personID);

                result = new PersonBAL().Insert(personID, txtFirstName.Text.Trim(), txtLastName.Text.Trim(), age);
                if (result > 0)
                {
                    MessageBox.Show("Record inserted successfully !");
                }
                else
                {
                    MessageBox.Show("No record afftected.");
                }
            }
            catch (Exception ee)
            {
                MessageBox.Show("Error occured. " + ee.Message);
            }
将参数值传递到数据库层的更正后的业务逻辑层代码如下所示;
C#:
public int Update(int personID, string textFirstName, string textLastName, int age)
        {           
            return new PersonDAL().Update(personID, textFirstName, textLastName, age);
        }
我没有使用void,因为我正在从表示层收集一些参数值并将它们传递给数据库层。我在这里错了吗?

最后,数据库层相关的更新代码,
C#:
 public int Update(int personID, string textFirstName, string textLastName, int age)
        {
            var returnValue = 0;

            using (SqlConnection conn = new SqlConnection(_connStr))

            {
                using (var dCmd = new SqlCommand(@"UPDATE Persons SET FirstName = @aFirstName, LastName = @aLastName, Age = @aAge
                                                            WHERE PersonID = @aPersonID", conn))     
                
                using (var adapter = new SqlDataAdapter { UpdateCommand = dCmd })

                {
                    conn.Open();
                    SqlParameter[] prms = new SqlParameter[4];
                    prms[0] = new SqlParameter("@aPersonID", SqlDbType.Int);
                    prms[0].Value = personID;
                    prms[1] = new SqlParameter("@aFirstName", SqlDbType.VarChar, 50);
                    prms[1].Value = textFirstName;
                    prms[2] = new SqlParameter("@aLastName", SqlDbType.VarChar, 50);
                    prms[2].Value = textLastName;
                    prms[3] = new SqlParameter("@aAge", SqlDbType.Int);
                    prms[3].Value = age;

                    dCmd.Parameters.AddRange(prms);

                    returnValue = dCmd.ExecuteNonQuery();
                    dCmd.Parameters.Clear();

                    adapter.Update(table);
                }

                foreach (DataRow row in table.Rows)
                {
                    if (row["Select Item"] as bool? == true)
                    {
                        table.AcceptChanges();
                        row.SetAdded();
                    }
                }
            }
            return returnValue;
        }

但是,现在的问题是,表示层中的代码未按预期执行。
C#:
result = new PersonBAL().Insert(personID, txtFirstName.Text.Trim(), txtLastName.Text.Trim(), age);

请感谢您的反馈。

亲切的问候,

安德鲁
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,524
地点
悉尼,澳大利亚
编程经验
10+
我知道这不是一个好的数据库设计。我的目标不是在此阶段进行良好的数据库设计,而是要了解CRUD操作在三层体系结构中的工作方式
那是糟糕的优先事项。如果您从一个糟糕的数据库设计开始,那么您可能必须在应用程序代码中做一些不必要的时髦事情来处理它。您应该先构建较低的层,然后再向上移动,直到要处理的层健全为止。首先设计一个好的数据库,然后设计一个可以使用它的好的DAL,然后构建一个好的BLL来访问数据,然后构建一个使用该业务逻辑的PL。当您变得更有经验时,您应该能够同时构建它们,但就目前而言,您将最终遇到复合错误。
 
最佳 底部