简体   繁体   English

使SqlDataAdapter / Datareader“真的只读”

[英]Making SqlDataAdapter/Datareader “Really Read-Only”

Updated Question: Is there a way to force dataadapter accept only commands which do not include any update/drop/create/delete/insert commands other than verifying the command.text before sending to dataadapter (otherwise throw exception). 更新的问题:有没有办法强制dataadapter只接受除了在发送到dataadapter之前验证command.text之外不包含任何update / drop / create / delete / insert命令的命令(否则抛出异常)。 is there any such built-in functionality provided by dot net in datareader dataadapter or any other? 是否在datareader dataadapter或其他任何其他网络中由dot net提供了这样的内置功能?

Note: DataReader returns results it also accepts update query and returns result. 注意:DataReader返回结果,它也接受更新查询并返回结果。 (I might be omitting some mistake but I am showing my update command just before executing reader and then show message after its success which is all going fine (我可能省略了一些错误,但是我在执行读者之前显示我的更新命令,然后在成功之后显示消息,这一切都很顺利

Could you search the string for some keywords? 你能在字符串中搜索一些关键字吗? Like CREATE,UPDATE, INSERT, DROP or if the query does not start with SELECT? 像CREATE,UPDATE,INSERT,DROP或者如果查询不以SELECT开头? Or is that too flimsy? 或者这太脆弱了?

You might also want to create a login for this that the application uses that only has read capability. 您可能还想为此应用程序创建仅具有读取功能的登录名。 I don't know if the object has that property but you can make the server refuse the transaction. 我不知道对象是否具有该属性,但您可以让服务器拒绝该事务。

All you need to do is ensure there are no INSERT, UPDATE, or DELETE statements prepared for the DataAdapter . 您需要做的就是确保没有为DataAdapter准备INSERT,UPDATE或DELETE语句。 Your code could look something like this: 您的代码可能如下所示:

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

OR 要么

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

And bam, you have a read-only data adapter. 而且,你有一个只读数据适配器。

If you just wanted a DataTable then the following method is short and reduces complexity: 如果您只是想要一个DataTable,那么以下方法很简短并降低了复杂性:

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;
            }

        }

    }

}

usage: 用法:

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

There isn't really a need to use the DataAdapter here - it's not really for what you want. 这里没有必要使用DataAdapter - 它并不是真正符合您的需求。 Why even go to the bother of catching exceptions etc if the Update, Delete or Insert commands are used? 如果使用更新,删除或插入命令,为什么还要去捕捉异常等? It's not a great fit for what you want to do. 它不适合你想做的事情。

It's important to note that the SelectCommand property doesn't do anything special - when the SelectCommand is executed, it will still run whatever command is passed to it - it just expects a resultset to be returned and if no results are returned then it returns an empty dataset. 重要的是注意 SelectCommand属性没有做任何特殊的事情 - 当执行SelectCommand时,它仍然会运行传递给它的任何命令 - 它只是期望返回一个结果集,如果没有返回结果,那么它返回一个空数据集。

This means that (and you should do this anyway) you should explicitly grant only SELECT permissions to the tables you want people to be able to query. 这意味着(无论如何你应该这样做)你应该只显示你希望人们能够查询的表的SELECT权限

EDIT 编辑

To answer your other question, SqlDataReader 's are ReadOnly because they work via a Read-Only firehose style cursor. 要回答你的另一个问题, SqlDataReaderReadOnly因为它们通过只读的firehose样式游标工作。 What this effectively means is: 这实际上意味着:

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;
}

It's read only because it doesn't allow you to update the records as you move through them. 它是只读的,因为它不允许您在浏览记录时更新记录。 There is no reason why the sql they execute to get the resultset can't update data though. 他们执行的sql获取结果集没有理由不能更新数据。

If you have a read-only requirement, have your TextBox use a connection string that uses an account with only db_datareader permissions on the SQL database. 如果您具有只读要求,请让TextBox使用连接字符串,该字符串使用仅对SQL数据库具有db_datareader权限的帐户。

Otherwise, what's stopping the developer who is consuming your control from just connecting to the database and wreaking havoc using SqlCommand all on their own? 否则,是什么阻止了开发人员只是连接到数据库并使用SqlCommand全部破坏了你的控制?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM