2017-04-07 34 views
1

我想在我的應用程序中使用gridview和SQLDataSource控件更新購物車,我試圖設置更新命令參數,以便我可以將值發送到我的SQL存儲過程,但它一直拋出一個異常,說它不能從nvarchar轉換爲字符串。UpdateCommand參數值總是一個字符串

鑑於下面的代碼;

ProductsDataSource.UpdateParameters.Add("Description", row.Cells[2].Text); 

看來,這種方法不會接受比,因爲它的第二個參數的String其他任何東西,所以我怎麼可以轉換到其他值傳遞到我的參數?

我已經嘗試過這樣的事情;

int productID = int.Parse(row.Cells[1].Text); 

卻自認爲第二個參數必須有一個字符串參數,我不能將其插入到我的DB(抱怨它不能隱式轉換爲字符串!)

+0

爲什麼你首先使用'SqlDataSource'?爲什麼不堅持使用普通的ADO.NET並使用'SqlConnection'和'SqlCommand'? – mason

+0

根本不使用'SqlDataSource'!現在你已經將數據庫代碼散佈到你的UI層。這不好!相反,您的數據庫操作應封裝到單獨的類中(通常放置在單獨的類庫中),並且您的頁面應獲取該類的實例以執行與數據庫的任何交互。您應該查看「存儲庫模式」。 – mason

+0

是否存在另一個超載,允許您在UpdateParameters.Add中指定類型( – McGaz

回答

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"); 
-3

嘗試 字符串=的productID(字符串)(row.Cells [1] .Text)

+2

將字符串投射到字符串? –

+0

用調試器查看返回的row.Cells [1] .Text如果返回的字符串不需要轉換爲字符串在另一種情況下,你需要轉換爲字符串 – LaFleur

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等之前進行批量更改,但這是一個基本實現。

在接口後面抽象數據庫交互的另一個優點是您可以嘗試不同的實現,而無需更改整個網站。想嘗試實體框架?創建一個新的EntityFrameworkProductRepository,實現IProductRepository。如果你想完全切換數據庫怎麼辦? SqlLite是免費和輕量級的,適用於小應用程序。創建一個新的SqlLiteProductRepository

+0

謝謝,我會研究這:) –

相關問題