对于此代码行
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);
}
答案 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);