为什么 "contains" 方法 returns 列表中的元素就好像它不在列表中一样?
Why does the "contains" method returns an element that is in the list as if it is not?
我的数据库中有一个产品 table。另外,我的数据库中有品牌和类别 table,它们彼此不相关。我想把这些联系起来。在表格 UI 中,当我单击其中一个类别时,应该出现他们在相关类别中拥有产品的品牌。
我试过这种方式来做到这一点。首先,我使用 GetList 方法通过 categoryID 获取我的产品,然后我获取这些产品的品牌,并将这些品牌添加到 pblist 列表(品牌类型)。但是,某些产品具有相同的品牌和 pblist 具有重复的品牌名称。我试图用 contains 方法解决这个问题,但它不起作用。另外,我在另一部分遇到了同样的问题,我试图从 blist(所有品牌列表)中删除未包含在 pblist 中的品牌。我尝试通过使用以下代码获取其索引来从 blist 中删除项目:blist.RemoveAt(blist.IndexOf(item));但这个也不是 working.It returns -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 中我分享了 filled methods 有更多的方法可以填充。
这是我的 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;
}
}
ProductService这个GetQuery方法,在其他服务中有一些不同但也有相似之处
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,
}
};
}
由于您不能确保同一品牌的两个不同实例不相等,
在“.Equals(object other)”returns true 的意义上,
“.Contains”方法无法识别它们。
我想你会通过重写 .Equals 来解决你的问题 Brand
class.
Entity framework 会将 Linq 查询转换为 SQL 语句,这意味着 Equals
(和 GetHashCode
)不会用于数据库对象的比较。但是,如果您要比较这些对象的 本地实例 ,则将使用这些方法进行比较。
默认值 Equals
进行引用比较以确定相等性,字面上的意思是,只有当一个类型的两个实例都引用内存中完全相同的对象时,它们才被视为相等。
相反,我们希望使用 ID
属性 进行相等比较,这意味着我们需要为 class.
这是一个如何执行此操作的示例:
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;
}
}
或者,如果您不想修改 class(我建议这样做,因为它可以解决所有问题),您可以修改代码以过滤掉任何具有相同 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);
}
}
我的数据库中有一个产品 table。另外,我的数据库中有品牌和类别 table,它们彼此不相关。我想把这些联系起来。在表格 UI 中,当我单击其中一个类别时,应该出现他们在相关类别中拥有产品的品牌。
我试过这种方式来做到这一点。首先,我使用 GetList 方法通过 categoryID 获取我的产品,然后我获取这些产品的品牌,并将这些品牌添加到 pblist 列表(品牌类型)。但是,某些产品具有相同的品牌和 pblist 具有重复的品牌名称。我试图用 contains 方法解决这个问题,但它不起作用。另外,我在另一部分遇到了同样的问题,我试图从 blist(所有品牌列表)中删除未包含在 pblist 中的品牌。我尝试通过使用以下代码获取其索引来从 blist 中删除项目:blist.RemoveAt(blist.IndexOf(item));但这个也不是 working.It returns -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 中我分享了 filled methods 有更多的方法可以填充。
这是我的 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;
}
}
ProductService这个GetQuery方法,在其他服务中有一些不同但也有相似之处
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,
}
};
}
由于您不能确保同一品牌的两个不同实例不相等, 在“.Equals(object other)”returns true 的意义上, “.Contains”方法无法识别它们。
我想你会通过重写 .Equals 来解决你的问题 Brand
class.
Entity framework 会将 Linq 查询转换为 SQL 语句,这意味着 Equals
(和 GetHashCode
)不会用于数据库对象的比较。但是,如果您要比较这些对象的 本地实例 ,则将使用这些方法进行比较。
默认值 Equals
进行引用比较以确定相等性,字面上的意思是,只有当一个类型的两个实例都引用内存中完全相同的对象时,它们才被视为相等。
相反,我们希望使用 ID
属性 进行相等比较,这意味着我们需要为 class.
这是一个如何执行此操作的示例:
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;
}
}
或者,如果您不想修改 class(我建议这样做,因为它可以解决所有问题),您可以修改代码以过滤掉任何具有相同 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);
}
}