2012-09-21 31 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自己連接到數據庫並肆意破壞您的控制權?