在SQL Compact查询内部和MVC3项目中检查null时出现问题

时间:2012-08-08 17:36:58

标签: c# sql asp.net-mvc-3 linq

我正在研究Pro ASP.NET MVC 3 Framework中的SportsStore示例。在第8章的开头,我被指示编辑我的ProductController类,添加.Where行如下:

    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位使代码运行得很好。
  • 我上面给出的第二个版本是他们网站上可下载的源代码。

没有空检查它确实有效,但我担心如果我继续前进我可能会在以后遇到问题。有没有人对我如何解决它有任何想法?

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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);

这允许您在返回数据之前对查询中的所有过滤进行操作,并且可以在任意条件下使用此技巧,而不会使其变得混乱。

答案 2 :(得分:0)

不确定它是否提供相同的输出,我认为应该看看这个......

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