非静态字段,方法或属性需要对象引用" CustDAL.AddNewCust(ref Customer)

时间:2018-04-02 13:24:08

标签: c# sql

对于此代码行

bool rowsAffected = CustDAL.AddNewCust(ref newCustomer);

我收到错误:

  

非静态字段,方法或属性需要对象引用   ' CustDAL.AddNewCust(ref Customer)

CustDAL中的代码看起来像

 public bool AddNewCust(ref Models.Customer newCustomer)
    {
        SqlCommand command = new SqlCommand
        {
            CommandText = string.Format("INSERT INTO CUSTOMER VALUES('{0}', '{1}', '{2}', '{3}','{4}')", newCustomer.Title, newCustomer.Forename, newCustomer.Surname, newCustomer.Address, newCustomer.PhoneNumber)
        };

        return ExecuteNonQuery(command);
    }

1 个答案:

答案 0 :(得分:2)

这个代码在几个不同的级别上很糟糕。

首先,这是SQL注入攻击的一扇门 如果有人将客户的标题设置为Title');DROP TABLE CUSTUMER;--,请注意猜测接下来会发生什么? 切勿将字符串与用户输入连接以创建SQL语句。而是使用参数化查询将用户输入安全地发送到数据库。 正确的insert语句如下所示:

INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)

第二次,如果您在Customer表中添加或删除列,您的代码就会中断。在编写插入语句时始终指定列列表 映像将新列添加到Customer表以获取中间名称。如果这样做,您当前的语句将会中断,因为列数将停止匹配值的数量。

第三次,如果newCustomer的任何字符串属性包含'char,你将获得异常 - 因为你的SQL会变成这样:

INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...

第四,您正在传递一个SqlCommand实例,您不会将其丢弃。 虽然不处置SqlCommand并不可怕,因为它不包含任何非托管资源,这是一个实现细节。事实是它正在实现IDisposable接口,因此应予以处置。您可以在this SO post上阅读更多相关信息。实现IDisposable接口的实例的最佳实践用法是using语句中的局部变量 -

using(var cmd = new SqlCommand(sql, con))
{
    //... do command stuff here
}

第五DbCommand.ExecuteNonQuery因某种原因返回int ExecuteNonQuery的返回值表示SQL语句影响的行数 如果您使用尝试插入多个记录或更新多个记录的查询,您可能需要知道实际插入或更新的记录的结果。
返回bool会隐藏调用代码中的数据。

第六次,无需通过引用传递newCustomer参数,除非该方法初始化Models.Customer的新实例并将其分配给newCustomer引用

因此,更好地实现AddNewCust方法可能看起来更像这样:

public int AddNewCust(ref Models.Customer newCustomer)
{
    var sql = "INSERT INTO CUSTOMER (Title, Forename, Surname, Address, PhoneNumber) VALUES (@Title, @Forename, @Surname, @Address, @PhoneNumber)";
    using(var command = new SqlCommand(sql))
    {
        command.Parameters.Add("@Title", SqlDbType.VarChar).Value = newCustomer.Title;
        command.Parameters.Add("@Forename", SqlDbType.VarChar).Value = newCustomer.Forename;
        command.Parameters.Add("@Surname", SqlDbType.VarChar).Value = newCustomer.Surname;
        //  fill in the rest of the parameters here...
        return ExecuteNonQuery(command); // change this method to return int...
    };
}

所有这一切,你得到的当前异常的原因是因为你试图执行一个实例成员,好像它是一个静态成员 - 我猜CustDAL是该类的名称,并且不是对该类实例的引用的名称 有关更多信息,请阅读this SO post 您应该首先创建CustDAL类的实例,然后才能访问它的非静态成员。由于DAL类可能应该在整个应用程序中使用,因此您应该在调用类中包含一个包含该引用的字段:

private CustDAL _custDal;

// in the constructor:

_custDal = new CustDAL();

// when you want to add a new customer:

var rowsAffected = _custDal.AddNewCust(newCustomer);