Cω是微軟研究院對下一代語言的探索。它擴充了C#的功能,更好的支援資料訪問(SQL和XML)和並發控制。
Cω的希望能方便的開發出更加可靠且維護性更好的軟體,其中一個重要的概念就是"儘早的發現錯誤"。
在下面的一個資料庫查詢的例子中將很好的體現出這一點。
現在我想得到一個在某個城市的員工名字的列表。(就使用SQL-Server預裝的Northwind資料庫)
下面給出最簡單的實現:
SqlDataAdapter da = new SqlDataAdapter( "SELECT * FROM Employees WHERE City='"+city+"'", nwindConn );
DataSet ds = new DataSet();
da.Fill(ds,"Employees");
foreach (DataRow dr in ds.Tables["Employees"].Rows)
{
string name = dr["LastName"].ToString();
int id = (int)dr["EmployeeID"];
Console.WriteLine( id + ": " + name);
}
讓我們來看看有哪些地方容易出錯:
1. city參數可能會被SQL注入攻擊利用.
2. 資料類型是弱類型,需要強制轉換類型,容易出現Runtime error.
3. 表名和列名都是文字,不是類型變數。編譯器無法做檢查,容易出現Runtime error.
(想必不少人碰到過寫錯表名,導致資料庫訪問出錯,而debug n久的事情.)
4. 查詢語句也是文字,同樣無法通過編譯檢查是否出錯,容易出現Runtime error.
通過使用SqlParameters以及Typed DataSet我們可以避免前三個問題
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Employees WHERE City= @city", nwindConn );
SqlParameter cityParam = da.SelectCommand.Parameters.Add("@city", SqlDbType.VarChar, 80);
cityParam.Value = city;
NorthwindDataSet ds = new NorthwindDataSet();
da.Fill(ds, ds.Employees.TableName );
foreach (NorthwindDataSet.EmployeesRow dr in ds.Employees.Rows)
{
string name = dr.LastName;
int id = dr.EmployeeID;
Console.WriteLine( id + ": " + name);
}
但是第四個問題仍沒有解決。也許你想到了 SQL stored procedure,就像下面這樣:
CREATE PROCEDURE EmployeesForCity
@City nvarchar(80) AS
SELECT EmployeeID, LastName FROM Employees WHERE City = @City
SqlCommand cmd = new SqlCommand( "dbo.EmployeesForCity", nwindConn );
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter cityParam = cmd.Parameters.Add("@city", SqlDbType.VarChar, 80);
cityParam.Value = city;
SqlDataAdapter da = new SqlDataAdapter( cmd );
NorthwindDataSet ds = new NorthwindDataSet();
da.Fill(ds, ds.EmployeesForCity.TableName );
foreach (NorthwindDataSet.EmployeesForCityRow dr in ds.EmployeesForCity.Rows)
{
string name = dr.LastName;
int id = dr.EmployeeID;
Console.WriteLine( id + ": " + name);
}
SQL查詢語句雖然不能在編譯器檢查,但是至少我們可以先在SQL-server中驗證stored procedure,
再運行我們的程式,比Runtime error好多了。但是萬一stored procedure改了,或者是資料庫改了,
那我們又會看到Runtime error。問題的根本在於我們的代碼和資料庫的聯絡實在是太弱了。對於一
個小程式就如此容易出現問題,那麼對於那種和資料庫緊密聯絡的大型應用就更別談了。
再來看看C-omega的解決方案:
rows = select * from DB.Employees where City == city;
foreach( row in rows )
{
string name = row.LastName.Value;
int id = row.EmployeeID.Value;
Console.WriteLine( id.ToString() + ": " + name);
}
以上代碼需要引起注意的地方:
1. 可以將本地變數city直接放入SQL語句,不會被SQL注入攻擊。
2. 結果集是強型別的,意味著在程式編譯的時候我們就知道資料庫的結構,甚至可以使用VS.net
所帶的智能感知(自動完成)功能。
3. 在rows以及row前面甚至沒有使用類型名,而它們卻都是強型別的。
4. 不再含有文字類型的資訊,避免了人為輸入錯誤。
5. 在程式編譯的時候就已經和資料庫連接,當資料庫發生變化的時候,在編譯器就會報錯。
如果你不喜歡SQL的文法,你甚至用三行代碼就能搞定以上所有任務。
DB.Employees [City==city].{
Console.WriteLine( it.EmployeeID + ": " + t.LastName );
};
從c++到C#我們常聽見的一句話就是c#是型別安全的。何謂型別安全?就是.Net Runtime支援編譯期的類型檢查。也就是盡量讓Runtime error變成Compile error,可以看出Cω在這個方面更進了一步。
註:鑒於個人水平以及資料方面的原因對其內部機制實現筆者並為做深入研究。
BTW 最近Yahoo新推出了一個Yahoo360度的新玩意,也是邀請制想要的朋友去這裡看看.