与其直接回答为什么您的代码不起作用,我想我会提出一个替代方案。即使你用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 之前对其进行批量更改等,但这是一个基本的实现。
将数据库交互抽象化为接口的另一个优点是,您可以尝试不同的实现,而无需更改整个网站。想尝试实体框架?创建一个实现IProductRepository 的新EntityFrameworkProductRepository。如果你想完全切换数据库怎么办? SqlLite 是免费且轻量级的,适用于小型应用程序。创建一个新的SqlLiteProductRepository。