使用SqlDataAdapter时,需要注意的几点

1、SqlDataAdapter内部通过SqlDataReader获取数据,而默认情况下SqlDataReader不能获知其查询语句对应的数据库表名,所以下面的代码:

string strConn,strSQL;

strConn=@"Data Source=.\SQLEXPRESS;"+"Initial Catalog=Northwind;Integrated Security=True;";

strSql="SELECT CustomerID,CompanyName FROM Customers";

SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);

DataSet ds=new DataSet();

da.Fill(ds);

会在DataSet中创建一个新的DataTable,这个新的DataTable会拥有名为CustomerID和CompanyName 列,但是DataTable对象的名称是Table,而不是我们希望的Customers

这个问题,可以通过添加TableMapping来解决:

string strConn,strSQL;

strConn=@"Data Source=.\SQLEXPRESS;"+"Initial Catalog=Northwind;Integrated Security=True;";

strSql="SELECT CustomerID,CompanyName FROM Customers";

SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);

da.TableMappings.Add("Table","Customers");

DataSet ds=new DataSet();

da.Fill(ds);

其实最简洁的方法是通过使用Fill方法的重载,通过指定DataTable,像这样:

SqlDataAdapter.Fill(DataSet,"MyTableName");

这样就可以不必使用TableMappings集合。

2、在使用Fill方式时,可以指定DataTable,而不是DataSet:

string strConn,strSQL;

strConn=@"Data Source=.\SQLEXPRESS;"+"Initial Catalog=Northwind;Integrated Security=True;";

strSql="SELECT CustomerID,CompanyName FROM Customers";

SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);

DataTable tbl=new DataTable();

da.Fill(tbl);

3、注意打开和关闭连接的处理

在调用SqlCommand对象执行sql命令之前,需要保证与该对象关联的SqlConnection对象时打开的,否则SqlCommand的方法执行时将引发一个异常,但是我们在上面的代码中看到,SqlDataAdapter没有这样的要求。

如果调用SqlDataAdapter的Fill方法,并且其SelectCommand属性的SqlConnection是关闭状态,则SqlDataAdapter会自动打开它,然后提交查询,获取结果,最后关闭连接。如果在调用Fill方法前,SqlConnection是打开的,则查询执行完毕后,SqlConnection还将是打开的,也就是说SqlDataAdapter会保证SqlConnection的状态恢复到原来的情形。

这有时会导致性能问题,需要注意,例如下面的代码:

string strConn,strSQL;

strConn=@"Data Source=.\SQLEXPRESS;"+"Initial Catalog=Northwind;Integrated Security=True;";

SqlConnection cn=new SqlConnection(strConn);

SqlDataAdapter daCustomers,daOrders;

strSql="SELECT CustomerID,CompanyName FROM Customers";

daCustomers=new SqlDataAdapter(strSql,cn);

strSql="SELECT OrderID,CustomerID,OrderDate  FROM Orders";

daOrders=new SqlDataAdapter(strSql,cn);

DataSet ds=new DataSet();

daCustomers.Fill(ds,"Customers");

daOrders.Fill(ds,"Orders");

以上代码会导致连接被打开和关闭两次,在调用Fill方法时各一次。为了避免打开和关闭SqlConnection对象,在调用SqlDataAdapter对象的Fill方法之前,我们可以先打开SqlConnection对象,如果希望之后关闭连接,我们可以再调用Close方法,就像这样:

cn.Open();

daCustomers.Fill(ds,"Customers");

daOrders.Fill(ds,"Orders");

cn.Close();

4、多次调用Fill方法需要注意数据重复和有效更新数据的问题

string strConn,strSQL;

strConn=@"Data Source=.\SQLEXPRESS;"+"Initial Catalog=Northwind;Integrated Security=True;";

strSql="SELECT CustomerID,CompanyName FROM Customers";

SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);

DataSet ds=new DataSet();

da.Fill(ds,"Customers");

…….

da.Fill(ds,"Customers");

我们分析上面的代码,通过两次调用Fill方法,SqlDataAdapter执行两次查询,并两次将查询结果保存到DataSet中,第一次调用在DataSet中创建了一个名为Customers的新表。第二次调用Fill方法将查询的结果追加到DataSet中的同一个表中,因此,每个客户的信息将在DataSet中出现两次!当然,如果数据库管理员对Customers表定义了主键,则SqlDataAdapter在天成DataTable时,会判断重复行,并自动丢弃掉旧的值。

考虑一下,假定一个特定客户在第一次调用Fill方法时,存储于数据库中,那么SqlDataAdapter会将其添加到新建的DataTable中。如果后来这个客户被删除了,那么第二次调用Fill方法时,SqlDataAdapter将不会在查询结果中找到该客户信息,但是它也不会将客户信息从DataSet中删除。这就导致了数据更新的问题。

所以推荐的做法是,在调用Fill方法前,先删除本地DataSet中缓存的数据!

在WPF中,使用`SqlDataAdapter`进行数据检索,虽然它不是直接涉及SQL语句编写,但依然需要注意防止SQL注入攻击。以下是几种推荐的做法: 1. **利用DataSet或DataTable**: `SqlDataAdapter`通常配合`DataSet`或`DataTable`使用,先创建一个空表,然后填充数据。你可以使用`Fill()`方法,其中的参数是一个预先声明好的表格对象,而不是直接构造SQL查询。这样可以避免将用户输入直接插入到SQL语句中: ```csharp string query = "SELECT * FROM MyTable"; DataSet dataSet = new DataSet(); SqlDataAdapter adapter = new SqlDataAdapter(query, connectionString); adapter.Fill(dataSet); ``` 2. **使用Command对象**: 尽管`SqlDataAdapter`内部可能会使用`SqlCommand`,但也可以显式地创建并配置`SqlCommand`,并使用参数化查询来防止注入: ```csharp string searchTerm = "test%"; SqlCommand command = new SqlCommand("SELECT * FROM MyTable WHERE Column LIKE @searchTerm", connection); command.Parameters.AddWithValue("@searchTerm", "%" + searchTerm + "%"); SqlDataAdapter adapter = new SqlDataAdapter(command); ``` 3. **处理用户输入**: 在实际应用中,对用户输入进行转义或过滤,移除可能导致SQL解析错误的关键字和特殊字符。 4. **启用数据库层防御**: 后台数据库服务器也应该有相应的安全配置,比如启用参数化查询功能或使用存储过程。 总之,关键在于避免在SQL语句中直接使用来自用户的输入作为动态部分。即使是通过`SqlDataAdapter`间接操作,也要确保其底层使用的命令对象进行了正确的参数化处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值