C# 非静态字段、方法或属性需要对象引用';客户添加新客户(参考客户)
对于此代码行C# 非静态字段、方法或属性需要对象引用';客户添加新客户(参考客户),c#,sql,C#,Sql,对于此代码行 bool rowsAffected = CustDAL.AddNewCust(ref newCustomer); 我得到一个错误: 非静态字段、方法或属性需要对象引用 'CustDAL.AddNewCust(参考客户) 奶油冻里的代码看起来像 public bool AddNewCust(ref Models.Customer newCustomer) { SqlCommand command = new SqlCommand {
bool rowsAffected = CustDAL.AddNewCust(ref newCustomer);
我得到一个错误:
非静态字段、方法或属性需要对象引用
'CustDAL.AddNewCust(参考客户)
奶油冻里的代码看起来像
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);
}
这段代码在几个不同的层面上都很糟糕 首先,它为SQL注入攻击打开了大门。
如果有人将客户的标题设置为,比如,
Title');升降台客户--代码>,想知道接下来会发生什么吗?
决不要将字符串与用户输入连接起来以创建SQL语句。相反,使用参数化查询将用户输入安全地发送到数据库。
正确的insert语句如下所示:
INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)
INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...
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...
};
}
第二个,如果从Customer表中添加或删除列,代码将中断。在编写insert语句时,始终指定列列表。
为中间名向Customer表中添加新列。如果这样做,当前语句将中断,因为列数将停止与值数匹配
第三个,如果newCustomer的任何字符串属性包含“char”,您将得到一个异常-因为您的SQL将变成如下所示:
INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)
INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...
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...
};
}
第四个,您正在传递一个SqlCommand实例,而不处理它。
虽然不处理SqlCommand
并不可怕,因为它不包含任何非托管资源,但这是一个实现细节。事实上,它正在实现IDisposable
接口,因此应该进行处理。你可以在网上读到更多关于这方面的内容。实现IDisposable
接口的实例的最佳实践用法是作为内的局部变量使用
station-
using(var cmd = new SqlCommand(sql, con))
{
//... do command stuff here
}
Fifth,DbCommand.ExecuteNonQuery
返回一个int值作为原因。
ExecuteNonQuery
的返回值表示受SQL语句影响的行数。
如果您使用的查询试图插入多条记录或更新多条记录,您可能需要知道这些记录如何实际插入或更新。
返回bool会对调用代码隐藏该数据
Sixth,通过引用传递newCustomer
参数没有意义,除非该方法初始化Models.Customer的新实例并将其分配给newCustomer
引用
因此,AddNewCust
方法的更好实现可能更像这样:
INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)
INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...
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
是类的名称,而不是该类实例的引用名称。
有关更多信息,请阅读
您应该首先创建CustDAL
类的实例,然后才能访问它的非静态成员。由于DAL类可能会在整个应用程序中使用,因此在调用类中可能会有一个包含该引用的字段:
private CustDAL _custDal;
// in the constructor:
_custDal = new CustDAL();
// when you want to add a new customer:
var rowsAffected = _custDal.AddNewCust(newCustomer);
这段代码在几个不同的层面上都很糟糕
首先,它为SQL注入攻击打开了大门。
如果有人将客户的标题设置为,比如,Title');升降台客户--代码>,想知道接下来会发生什么吗?
决不要将字符串与用户输入连接起来以创建SQL语句。相反,使用参数化查询将用户输入安全地发送到数据库。
正确的insert语句如下所示:
INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)
INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...
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...
};
}
第二个,如果从Customer表中添加或删除列,代码将中断。在编写insert语句时,始终指定列列表。
为中间名向Customer表中添加新列。如果这样做,当前语句将中断,因为列数将停止与值数匹配
第三个,如果newCustomer的任何字符串属性包含“char”,您将得到一个异常-因为您的SQL将变成如下所示:
INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)
INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...
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...
};
}
第四个,您正在传递一个SqlCommand实例,而不处理它。
虽然不处理SqlCommand
并不可怕,因为它不包含任何非托管资源,但这是一个实现细节。事实上,它正在实现IDisposable
接口,因此应该进行处理。你可以在网上读到更多关于这方面的内容。实现IDisposable
接口的实例的最佳实践用法是作为内的局部变量使用
station-
using(var cmd = new SqlCommand(sql, con))
{
//... do command stuff here
}
Fifth,DbCommand.ExecuteNonQuery
返回一个int值作为原因。
ExecuteNonQuery
的返回值表示受SQL语句影响的行数。
如果您使用的查询试图插入多条记录或更新多条记录,您可能需要知道这些记录如何实际插入或更新。
返回bool会对调用代码隐藏该数据
Sixth,通过引用传递newCustomer
参数没有意义,除非该方法初始化Models.Customer的新实例并将其分配给newCustomer
引用
因此,AddNewCust
方法的更好实现可能更像这样:
INSERT INTO TableName(Column1, Column2....Columnn) VALUES(@Param1, @Param2...@Paramn)
INSERT INTO CUSTOMER VALUES('My title isn't that smart', 'My forename',...
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
是类的名称,而不是该类实例的引用名称。
有关更多信息,请阅读
您应该首先创建CustDAL
类的实例,并且只创建