我正在尝试使用gridview和SQLDataSource控件更新我的应用程序中的购物车,我正在尝试设置更新命令参数,以便我可以将值发送到我的SQL存储过程,但它不断抛出异常说它无法从nvarchar转换为字符串。
鉴于以下代码;
ProductsDataSource.UpdateParameters.Add("Description", row.Cells[2].Text);
似乎这个方法不会接受除String以外的任何东西,因为它是第二个参数,那么如何将其转换为其他值以传递给我的参数呢?
我已经尝试过这样的事情;
int productID = int.Parse(row.Cells[1].Text);
但由于第二个参数HAS有一个字符串参数,我无法将其插入到我的数据库中(抱怨它不能隐式转换为字符串!)
答案 0 :(得分:2)
我认为我不会直接回答你的代码无法正常工作的原因。即使您使用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
之前进行批量更改,但这是一个基本实现。
在界面后面抽象数据库交互的另一个好处是,您可以尝试不同的实现,而无需更改整个网站。想尝试Entity Framework吗?创建一个实现EntityFrameworkProductRepository
的新IProductRepository
。如果要完全切换数据库怎么办? SqlLite是免费且轻量级的,适用于小型应用程序。创建一个新的SqlLiteProductRepository
。
答案 1 :(得分:1)
您可以在标记上指定参数类型..
<UpdateParameters >
<asp:Parameter Name="paramName" DbType="String" Type="String" />
你可以在背后的代码上设置值。
ProductsDataSource.UpdateParameters["paramName"].DefaultValue = "parameter value";
或者您可以使用Add方法的重载而不使用标记定义。
SqlDataSource1.UpdateParameters.Add("paramName", DbType.String, "parameter value");
答案 2 :(得分:-3)
尝试 string productID =(string)(row.Cells [1] .Text)