1

Pro ASP.NET MVC 3 Frameworkの SportsStore の例に取り組んでいます。第 8 章の冒頭で、次のように .Where 行を追加して、ProductController クラスを編集するように指示されました。

    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>

かなり検索したところ、このStackOverflow投稿への参照が複数の場所で見つかりましたが、クエリを次のように変更しました

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

効果がありませんでした。

いくつかの基本情報:

  • これは、Razer ビュー エンジンと C# を使用した MVC3 プロジェクトです。
  • 私の SQL Compact 4.0 データベースのすべてのアイテムにはカテゴリがあります。
  • カテゴリ == null ビットをコメント アウトすると、コードが正常に実行されます。
  • 上記の 2 番目のバージョンは、サイトからダウンロード可能なソース コードに含まれるものです。

nullチェックなしで動作しますが、先に進むと後で問題が発生するのではないかと心配しています。どうすれば修正できるかについて誰かアイデアがありますか?

4

3 に答える 3

1

問題は、LINQ クエリが SQL サーバーに到達するまで延期されていることだと思います。私の推測では、SQL コンパクト サーバーのチェックに問題があると思われます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);
于 2012-08-08T21:07:36.020 に答える
1

同じ問題ですが、結果で返したくない関連テーブルに WHERE 句があるため、マークされた回答は機能しません。また、すべてを返し、後で .Where() を実行するのは非常に非効率的です。

より良い方法は次のとおりです。

SQL CE はパラメータを処理できないため、標準的な構造

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

クエリ内でその値の比較を行うには、LINQ がパラメーターを使用する必要があるため、失敗します。しかし、次のようなものを渡すことは完全に有効な SQL です。

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

「true」は常に...うーん...trueだからです。したがって、LINQ ステートメントの前に変数を bool に解析し、その変数を SQL CE に渡すと、適切な状態になります。

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

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

これにより、データを返す前にクエリ内のすべてのフィルタリングを行うことができ、面倒になることなく、必要な数の条件でこのトリックを使用できます。

于 2013-03-21T21:50:58.473 に答える
0

同じ出力が得られるかどうかはよくわかりませんが、これを見てください...

 Products = repository.Products
            .Where(p => p.Category == null || p.Category == category)
            .OrderBy(p => p.ProductID)
            .Skip((page - 1) * PageSize)
            .Take(PageSize),
于 2012-08-08T17:49:34.637 に答える