而不是直接回答爲什麼你的代碼不工作,我想我會提出一個替代方案。即使您用SqlDataSource
修復錯誤,我認爲從長遠來看繼續使用也是不好的。使用SqlDataSource
作爲網頁上的控件將數據庫代碼散佈在UI層中。這非常混亂,我們儘量避免使用現代應用程序。 SqlDataSource
也鼓勵神奇的字符串,而不是使用強類型的模型對象。
更好的選擇是完全拋棄SqlDataSource
並直接使用ADO.NET(可能通過一些微型ORM,例如Dapper)。我們也可以將這個邏輯轉移到它自己的類中,並遵循存儲庫模式。該類最好放在單獨的類庫中,以便應用程序隨後引用它,然後可以從其他應用程序中重用該類。我個人經常有一個控制檯應用程序,這樣我就可以測試我的存儲庫的一些部分,而無需瀏覽網站。
不是讓你的網站直接依賴這個存儲庫類,我們經常通過一個接口工作。這使我們的網站不需要直接依賴於數據庫邏輯的實現方式。這通常與依賴注入結合在一起,但這對於這篇文章來說有點太大了。我強烈建議你查看關於依賴注入的this excellent video。
所以,這裏是我們的接口:
public interface IProductRepository
{
Product GetProductById(int id);
void UpdateProduct(Product product);
List<Product> GetAllProducts();
}
現在的實際執行情況:
public class SqlServerProductRepository: IProductRepository
{
private readonly string _connectionString;
public ProductRepository(string connectionString)
{
_connectionString = connectionString;
}
public Product GetProductById(int id)
{
using(var connection = new SqlConnection(_connectionString))
{
//QuerySingle is an extension method from Dapper
return connection.QuerySingle<Product>("select Name, Description, Id from Products where Id = @Id", new {Id = id});
}
}
public void UpdateProduct(Product product)
{
using(var connection = new SqlConnection(_connectionString))
{
//Execute is an extension method from Dapper
connection.Execute("update Products set Name = @Name, Description = @Description where Id = @Id", product);
}
}
public List<Product> GetAllProducts()
{
using(var connection = new SqlConnection(_connectionString))
{
//Query is an extension method from Dapper
//You'd likely want to implement filters/paging etc in a real world app
return connection.Query<Product>("select Name, Description, Id from Products").AsList();
}
}
}
你需要一個模型類,如果你沒有一個現有的:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
現在您的網站中的代碼變得更加簡單:
//you can remove the direct reference to SqlServerProductRepository
//via Dependency Injection, not shown here
IProductRepository productRepository = new SqlServerProductRepository(connectionString);
var product = productRepository.GetProductById(1);
product.Description = "Updated Description";
productRepository.UpdateProduct(product);
ProductsGridView.DataSource = productRepository.GetAllProducts();
ProductsGridView.DataBind();
還有其他方法可以實現您的存儲庫,比如在調用SaveChanges
等之前進行批量更改,但這是一個基本實現。
在接口後面抽象數據庫交互的另一個優點是您可以嘗試不同的實現,而無需更改整個網站。想嘗試實體框架?創建一個新的EntityFrameworkProductRepository
,實現IProductRepository
。如果你想完全切換數據庫怎麼辦? SqlLite是免費和輕量級的,適用於小應用程序。創建一個新的SqlLiteProductRepository
。
爲什麼你首先使用'SqlDataSource'?爲什麼不堅持使用普通的ADO.NET並使用'SqlConnection'和'SqlCommand'? – mason
根本不使用'SqlDataSource'!現在你已經將數據庫代碼散佈到你的UI層。這不好!相反,您的數據庫操作應封裝到單獨的類中(通常放置在單獨的類庫中),並且您的頁面應獲取該類的實例以執行與數據庫的任何交互。您應該查看「存儲庫模式」。 – mason
是否存在另一個超載,允許您在UpdateParameters.Add中指定類型( – McGaz