2012-09-21 32 views
1

更新问题:有没有办法强制dataadapter只接受除发送前验证command.text之外不包含任何update/drop/create/delete/insert命令的命令到dataadapter(否则抛出异常)。 datareader dataadapter或其他任何网络中的dot net提供了哪些内置功能?使SqlDataAdapter/Datareader“真正只读”

注意:DataReader返回结果,它也接受更新查询并返回结果。 (我可能会省略一些错误,但是在执行读取器之前显示我的更新命令,然后在成功之后显示消息,这一切都很顺利

+0

duplicate - http://stackoverflow.com/questions/4900630/dataadapter-fill-command-prohibit-write-operation – Tobsey

+0

另一种选择可能是使用DataTable.Load方法带一个SqlDataReader,所以你没有除了DataTable.Load(command.ExecuteReader())以外的任何其他操作。 – dash

+0

另外请注意,你不应该仅仅依靠这一点 - 确保你恰当地允许表的SELECT权限('GRANT SELECT ON [Table] TO [User]')。有人可能按照SELECT * FROM User; DROP TABLE User;的语句输入内容:这在技术上是一个返回结果集的sql语句:SelectCommand属性就是将抽象数据加载到适配器中 - 它不会做任何事情来防止错误的sql被运行。 – dash

回答

2

您可以搜索某些关键字的字符串吗?就像CREATE,UPDATE,INSERT, DROP,或者如果查询不是以SELECT开头的,还是那太脆弱了?

您可能还想为应用程序创建一个只具有读取功能的登录名,但我不知道该对象是否具有该属性,但你可以让服务器拒绝交易

+0

是的,这是我错过了在我的问题中提到的选项。但我正在寻找一些技术上坚实的。也在这里,我必须使用正则表达式,我想避免 – Sami

+2

然后,我会去与路由2.建立一个服务器登录,只有dataReader。然后,使用Mike的解决方案,它使用此登录名作为连接字符串。然后,即使他们试图处理除SELECT以外的其他东西,服务器也会说不。你可以用trycatch或其他东西来处理这个异常。 – Bmo

+0

@Bmo,很好的结合。 –

1

所有你需要做的是确保没有为DataAdapter准备好INSERT,UPDATE或DELETE语句。我们的代码可能是这个样子:

var dataAdapter = new SqlDataAdapter("SELECT * FROM table", "connection string"); 

OR

var dataAdapter = new SqlDataAdapter("SELECT * FROM table", sqlConnectionObject); 

和BAM,您有一个只读的数据适配器。

1

如果你只是想要一个数据表,然后下面的方法很短,降低了复杂性:

public DataTable GetDataForSql(string sql, string connectionString) 
{ 
    using(SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     using(SqlCommand command = new SqlCommand()) 
     { 
      command.CommandType = CommandType.Text; 
      command.Connection = connection; 
      command.CommandText = sql; 
      connection.Open();   
      using(SqlDataReader reader = command.ExecuteReader()) 
      { 
       DataTable data = new DataTable(); 
       data.Load(reader); 
       return data; 
      } 

     } 

    } 

} 

用法:

try{ 
    DataTable results = GetDataForSql("SELECT * FROM Table;", ApplicationSettings["ConnectionString"]); 
} 
catch(Exception e) 
{ 
    //Logging 
    //Alert to user that command failed. 
} 

是不是真的有必要在这里使用DataAdapter - 这是不是真的为了你想要的。如果使用更新,删除或插入命令,为什么还要去捕捉异常等等?它不适合你想要做的事情。

这是重要的SelectCommand属性没有做什么特别的东西 - 在执行SelectCommand中时,它仍然会运行任何命令传递给它 - 它只是expects一个结果被返回,如果没有结果返回,那么它返回一个空的数据集。

这意味着(你应该这样做),你应该显式授予SELECT权限到你希望人们能够查询的表。

编辑

为了回答您的其他问题,SqlDataReader的是ReadOnly,因为他们通过只读流水式的游标工作。这实际上意味着什么:

while(reader.Read()) //Reads a row at a time moving forward through the resultset (`cursor`) 
{ 
    //Allowed 
    string name = reader.GetString(reader.GetOrdinal("name")); 
    //Not Allowed - the read only bit means you can't update the results as you move through them 
    reader.GetString(reader.GetOrdina("name")) = name; 
} 

它是只读的,因为它不允许您在遍历它们时更新记录。没有理由说为什么他们执行得到结果集的sql不能更新数据。

+0

你见过我的更新吗? Iam使用相同的,但奇怪的是它接受更新查询 – Sami

+1

@John这是因为他们都只是执行你传递给它的SQL。做你想做的唯一可行的方法是在数据库级别限制权限。 SqlDataReader和SelectCommand是关于从sql查询返回结果集的 - 它们不限制查询本身 - 你必须这样做:-) – dash

+0

例如:'SELECT * FROM Table;更新表SET Name ='Stinky';'是返回结果的完全有效的SQL语句 - 您可以将其提供给数据读取器或SelectCommand。 – dash

0

如果您有只读要求,请让TextBox使用连接字符串,该连接字符串只使用具有SQL数据库上的db_datareader权限的帐户。

否则,什么阻止了开发人员正在使用SqlCommand自己连接到数据库并肆意破坏您的控制权?