【问题标题】:Linq Entity Framework where parameter on joined tableLinq 实体框架连接表上的参数
【发布时间】:2013-11-19 11:01:15
【问题描述】:

我试图在连接表上的 linq 查询中添加 where 参数,我有一个产品列表显示在 ProductsListViewModel 中的 Products 表中,需要通过 ProductFilters 表中的 FilterId 参数进行过滤,SKU 为链接的字段,但不能在 where 子句中添加 FilterId 参数。

这是我目前拥有的 ViewModel 代码:

public class ProductsListViewModel
{
    public IEnumerable<Product> Products { get; set; }
    public PagingInfo PagingInfo { get; set; }
    public string CurrentCategory { get; set; }
    public IEnumerable<ProductFilter> ProductFilters { get; set; }
}

控制器:

public ViewResult List(string category, string filtermaterial = null, string filterlength = null, string filtername = null, string filterid = null, int page = 1)
{ 
    ProductsListViewModel viewModel = new ProductsListViewModel
    { 
        Products = repository.Products
        .Where(p => category == null || p.Category == category)
        .Where(p => filtermaterial == null || p.FilterMaterial == filtermaterial)
        .Where(p => filterlength == null || p.FilterLength == filterlength)
        .OrderBy(p => p.ProductID)
        .Skip((page - 1) * PageSize)
        .Take(PageSize),

        PagingInfo = new PagingInfo
        {
            CurrentPage = page,
            ItemsPerPage = PageSize,
            TotalItems = category == null ?
                repository.Products.Count() :
                repository.Products.Where(e => e.Category == category).Count()
        },

        CurrentCategory = category
    };

    ViewBag.Category = category;
    return View(viewModel);
}

Product 模型:

public class Product
{
    [HiddenInput(DisplayValue = false)]
    public int ProductID { get; set; }

    [Required(ErrorMessage = "Please enter a product name")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Please enter the SKU for this product")]
    public string SKU { get; set; }

    public string MainImage { get; set; }

    [DataType(DataType.MultilineText)]
    [Required(ErrorMessage = "Please enter a description")]
    public string Description { get; set; }

    [DataType(DataType.MultilineText)]
    [Required(ErrorMessage = "Please enter product specification details")]
    public string Specification { get; set; }

    [Required]
    [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a correct price")]
    public decimal Price { get; set; }

    [Required(ErrorMessage = "Please enter the Product Category")]
    public string Category { get; set; }

    //public int CategoryID { get; set; }

    [Required(ErrorMessage = "Please enter the Product Group")]
    public string ProductGroup { get; set; }

    [Required(ErrorMessage = "Please enter the search terms for this product")]
    public string SearchTerms { get; set; }

    public string FilterMaterial { get; set; }
    public string FilterLength { get; set; }
    public string Manufacturer { get; set; }
    public string Brand { get; set; }
    public string Details1 { get; set; }
    public string Details2 { get; set; }
    public string Details3 { get; set; }
    public string Details4 { get; set; }
    public string Spec1 { get; set; }
    public string Spec2 { get; set; }
    public string Spec3 { get; set; }
    public string Spec4 { get; set; }

    public virtual IQueryable<ProductFilter> ProductFilters { get; set; }
}

ProductFilter 模型:

public class ProductFilter
{
    [Key]
    public int FilterId { get; set; }
    public string Filtername { get; set; }
    public string CategoryGroup { get; set; }
    public string SKU { get; set; }
}

带连接的修改控制器

    public ViewResult List(string category, string filtermaterial = null, string filterlength = null, string filtername = null, string filterId = null, int page = 1)
    {         
        ProductsListViewModel viewModel = new ProductsListViewModel
        { 
            Products = repository.Products
            .Join(repository.ProductFilters, prod => prod.SKU, prodfilt => prodfilt.SKU, (prod, prodfilt) => new { Prod = prod, Prodfilt = prodfilt})
            .Where(p => category == null || p.Prod.Category == category)
            .Where(p => filtermaterial == null || p.Prod.FilterMaterial == filtermaterial)
            .Where(p => filterlength == null || p.Prod.FilterLength == filterlength)
            .Where(f => filterId == null || f.Prodfilt.FilterId == filterId)
            .OrderBy(p => p.Prod.ProductID)
            .Skip((page - 1) * PageSize)
            .Take(PageSize),
            PagingInfo = new PagingInfo
            {
                CurrentPage = page,
                ItemsPerPage = PageSize,
                TotalItems = category == null ?
                    repository.Products.Count() :
                    repository.Products.Where(e => e.Category == category).Count()
            },
            CurrentCategory = category
        };
        ViewBag.Category = category;
        return View(viewModel);
    }

【问题讨论】:

  • 你当前的 LINQ 是什么样子的
  • 为什么看起来您从 Product 类中删除了 ProductFiletrs?有了这个,你可以简单地添加.Where(p =&gt; p.ProductFilters.Any(pf =&gt; pf.FilterId == filterID))
  • 我的错误,我之前已经注释掉了产品模型的最后一行,试图解决复数命名的问题。我尝试添加 .Where(p => p.ProductFilters.Any(pf => pf.FilterId == filterID)) 但收到此错误消息 LINQ to Entities 不支持指定的类型成员“ProductFilters”。仅支持初始化器、实体成员和实体导航属性。
  • 你需要在product和productfilter之间加入..这样会更加优雅和高效。
  • 我想我已经正确地创建了连接并添加了过滤器,但我现在得到一个错误'无法将类型'System.Linq.IQueryable 隐式转换为 System.Collections.Generic。 IEnumerable。为了清楚起见,我已将修改后的控制器代码与连接添加到主要问题中。

标签: c# asp.net-mvc linq entity-framework viewmodel


【解决方案1】:

'System.Linq.IQueryable&lt;AnonymousType#1&gt; to System.Collections.Generic.IEnumerable&lt;WebStore.Domain.Entities.Product&gt;

您的 Viewmodel 需要 IEnumerable&lt;Product&gt; 类型的属性。通过将 Products 与 Productfilters 连接起来,返回的实体是匿名类型的。

要解决这个冲突,你需要添加一个强类型的 select 语句:

Products = repository.Products
        .Join(repository.ProductFilters, prod => prod.SKU, prodfilt => prodfilt.SKU, (prod, prodfilt) => new { Prod = prod, Prodfilt = prodfilt})
        // ...
        .Select( x => new Product { ... }) //add this and clarify the properties.
        .Skip((page - 1) * PageSize)
        .Take(PageSize)

或者你改变你的 ViewModel

public class ProductsListViewModel
{
    public IEnumerable<ProductAndFilterVM> FilterProducts { get; set; }
    public PagingInfo PagingInfo { get; set; }
    public string CurrentCategory { get; set; }
    public IEnumerable<ProductFilter> ProductFilters { get; set; }
}

这将要求您创建另一个 ViewModel,它代表连接的实体。但是你仍然需要选择。

【讨论】:

  • 我只是在尝试一些代码,被匿名类型弄糊涂了,只是尝试添加似乎可以工作并显示正确数据的 .Select(p => p.Prod),你认为这样可以吗,还是我应该在新产品中声明所有必需的字段 { ... }
  • 不,如果您需要的每个属性都可用,我会让它保持原样。如果您想刮掉最后一点多余的数据,请明确定义您需要什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多