首页 > 解决方案 > 为什么“包含”方法返回一个在列表中的元素,就好像它不在?

问题描述

我的数据库中有一个产品表。此外,我的数据库中有品牌和类别表,它们彼此不相关。我想把这些联系起来。当我单击其中一个类别时,在表单 UI 中,应该出现他们在相关类别中拥有产品的品牌。

我试过这种方式来做到这一点。首先,我使用 GetList 方法按 categoryID 获取我的产品,然后获取这些产品的品牌,并将这些品牌添加到 pblist 列表(品牌类型)中。但是,有些产品具有相同的品牌,并且 pblist 具有重复的品牌名称。我试图用 contains 方法解决这个问题,但它不起作用。另外,我在另一部分有同样的问题,我试图从 blist(所有品牌的列表)中删除 pblist 中未包含的品牌。我尝试通过使用以下代码获取其索引来从 blist 中删除项目: blist.RemoveAt(blist.IndexOf(item)); 但这一个也不起作用。它返回-1。但是项目在列表中。

 public class BrandVM : BaseVM
{
    public int ProductCount { get; set; }

}

 public class BaseVM
{
    public int ID { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return this.Name;
    }

 public class BrandService : ServiceBase, IBrandService
{


    public List<BrandVM> GetList(int Count)
    {
        try
        {
            var result = GetQuery();
            result = Count > 0 ? result.Take(Count) : result;

            return result.ToList();
        }
        catch (Exception ex)
        {

            return null;
        }
    }


public List<BrandVM> GetListByCatID(int pCatID)
    {
        var plist = productService.GetListByCatID(pCatID);
        List<BrandVM> pblist = new List<BrandVM>();
        foreach (var item in plist)
        {
            if (!pblist.Contains(item.Brand))
            {
                pblist.Add(item.Brand);
            }
        };

        var blist = GetList(0);
        var blistBackup = GetList(0);

        foreach (BrandVM item in blistBackup)
        {
            if (!pblist.Contains(item))
            {
                blist.Remove(item);
            }       
        };

        return blist;
    } 

这些是我与品牌相关的课程。在 BrandService 中,我分享了填充方法,还有更多方法可以填充。

这是我的 ProductService 中的方法:我使用该方法按 CategoryID (plist) 提取产品列表

public List<ProductVM> GetListByCatID(int EntityID)
    {
        try
        {
            var result = GetQuery().Where(x => x.Category.ID==EntityID);

            return result.ToList();
        }
        catch (Exception ex)
        {

            return null;
        }
    }

这个GetQuery方法是针对ProductService的,在其他服务中有一些区别但也有类似的

  private IQueryable<ProductVM> GetQuery()
    {
        return from p in DB.Products
               select new ProductVM
               {
                   ID = p.ProductID,
                   Name = p.ProductName,
                   UnitPrice = (decimal)p.UnitPrice,
                   Category =p.CategoryID==null?null:new CategoryVM()
                   {
                       ID = (int)p.CategoryID,
                       Name = p.Category.CategoryName
                   },
                   Brand = p.BrandID == null ? null :
                   new BrandVM
                   {
                           ID=(int)p.BrandID,
                           Name=p.Brand.BrandName,

                   }


               };
    }

标签: c#.netlistcontains

解决方案


实体框架会将 Linq 查询转换为 SQL 语句,这意味着Equals(and GetHashCode) 不会用于数据库对象的比较。但是,如果您要比较这些对象的本地实例,那么这些方法将用于比较。

默认值Equals会进行引用比较以确定相等性,这实际上意味着一个类型的两个实例只有在它们都引用内存中完全相同的对象时才被认为是相等的。

相反,我们希望使用该ID属性进行相等比较,这意味着我们需要覆盖类的Equals(and GetHashCode) 方法。

这是一个如何执行此操作的示例:

public class BaseVM
{
    public int ID { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return Name;
    }

    public override bool Equals(object obj)
    {
        return obj is BaseVM &&
               ((BaseVM) obj).ID == ID;
    }

    public override int GetHashCode()
    {
        return ID;
    }
}

或者,如果您不想修改该类(我建议这样做,因为它可以在任何地方解决这个问题),您可以修改您的代码以过滤掉任何具有相同 id(或名称)的品牌:

foreach (var item in plist)
{
    // Note: you could potentially use 'Name' instead of 'Id'
    if (!pblist.Any(productBrand => productBrand.Id == item.Brand.Id))
    {
        pblist.Add(item.Brand);
    }
}

推荐阅读