2012-08-08 49 views
1

我正在通過Pro ASP.NET MVC 3 Framework的SportsStore示例進行工作。在第8章的開始,我正在責成編輯我ProductController的類,添加。凡行,如下所示:檢查內部SQL查詢和MVC3項目中的null時遇到問題

public ViewResult List(string category, int page = 1) 
    { 
     ProductsListViewModel viewModel = new ProductsListViewModel 
     { 
      Products = repository.Products 
       .Where(p => category == null || p.Category == category) 
       .OrderBy(p => p.ProductID) 
       .Skip((page - 1) * PageSize) 
       .Take(PageSize), 
      PagingInfo = new PagingInfo 
      { 
       CurrentPage = page, 
       ItemsPerPage = PageSize, 
       TotalItems = repository.Products.Count() 
      }, 
      CurrentCategory = category 
     }; 
     return View(viewModel); 
    } 

當我運行代碼,我收到以下錯誤:

Exception Details: System.Data.SqlServerCe.SqlCeException: The specified argument 
value for the function is not valid. [ Argument # = 1,Name of 
function(if known) = isnull ] 

上在下面的代碼塊中的foreach行:

@model SportsStore.WebUI.Models.ProductsListViewModel 

@{ 
    ViewBag.Title = "Products"; 
} 

@foreach (var p in Model.Products) 
{ 
    Html.RenderPartial("ProductSummary", p); 
} 
<div class="pager"> 
    @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new {page = x})) 
</div> 

我已經搜查好位,並在多個地方發現了大量的引用來this StackOverflow post,但改變查詢

.Where(p => category == null ? true : p.Category == category) 

沒有效果。

的一些基本信息:

  • 這是使用Razer的視圖引擎和C#的MVC3項目。
  • 我的SQL Compact 4.0數據庫中的所有項目都有一個類別。
  • 註釋類別== null位使代碼運行得很好。
  • 我上面給出的第二個版本是從他們的網站下載的源代碼。

它沒有空檢查工作,但我擔心,如果我只是繼續前進,我可能會遇到問題後。有沒有人有任何想法,我怎樣才能解決它?

+0

你在哪一行發生錯誤? – Yasser 2012-08-08 17:43:10

+0

發生此錯誤: @foreach(Model.Products中的var p) – 2012-08-08 17:45:08

+0

我對MVC3一無所知,但是如果您提到SQL Compact Edition,那麼這可能是null/DBNull的問題(只是猜測......) )? – Gorgsenegger 2012-08-08 19:04:17

回答

1

我認爲問題是,LINQ查詢被推遲,直到它到達SQL服務器。我的猜測是SQL compact服務器在檢查category == null時遇到問題。

嘗試在調用Where方法之前使用非延遲LINQ方法。喜歡的東西

Products = repository.Products.ToList() 
    .Where(p => category == null || p.Category == category) 
    .OrderBy(p => p.ProductID) 
    .Skip((page - 1) * PageSize) 
    .Take(PageSize); 
+0

這實際上工作完美。謝謝! – 2012-08-08 21:11:03

+0

@Gurrgg這將導致所有*產品被加載到內存中,並且過濾,排序和分頁都將在內存中完成。如果有大量的產品,這將徹底癱瘓應用程序。 – 2013-10-02 08:22:56

0

還不是很確定,如果它提供了相同的輸出,我認爲它應該,對此看看...

Products = repository.Products 
      .Where(p => p.Category == null || p.Category == category) 
      .OrderBy(p => p.ProductID) 
      .Skip((page - 1) * PageSize) 
      .Take(PageSize), 
+0

我也考慮過這個,但我認爲其目的是顯示與給定類別相匹配的項目,並且如果沒有顯示所有項目。不過,我可能是錯的。 – 2012-08-08 17:54:19

1

同樣的問題,但由於我的WHERE子句是,我不希望在結果返回相關表中明顯的答案並不爲我工作。另外,返回所有內容然後再執行.Where()是非常低效的。

這裏有一個更好的辦法:

SQL CE不能處理參數,這樣,所謂標準建設

.Where(p => p.Category == category || category == null) 

失敗,因爲LINQ需要使用參數來完成在查詢該值進行比較。但它是完全有效的SQL通過這樣的事情:

.Where(p => p.Category == category || true) 

因爲'真'總是......好......真。所以,如果你的LINQ語句之前解析您的變量爲BOOL,然後傳遞變量SQL CE,你是在良好的狀態:

bool bCategory = (string.IsNullOrEmpty(category)) ? true : false; 

Products = repository.Products.Where(p => p.Category == category || bCategory); 

這樣就可以將數據返回之前做查詢中的所有濾波,並且您可以在儘可能多的條件下使用這個技巧,而不會讓它變得混亂。