C# 返回重复项的递归linq结果
这个问题是我上周问的一个问题的基础:。那篇文章给出的答案产生了我所需要的;基于父级的位置及其子级的独特列表。我们需要使用我们自己的位置模型,所以我们创建了一个,从那以后,我得到了重复的结果。我们的模型非常基本:C# 返回重复项的递归linq结果,c#,asp.net-mvc,entity-framework,linq,linq-to-entities,C#,Asp.net Mvc,Entity Framework,Linq,Linq To Entities,这个问题是我上周问的一个问题的基础:。那篇文章给出的答案产生了我所需要的;基于父级的位置及其子级的独特列表。我们需要使用我们自己的位置模型,所以我们创建了一个,从那以后,我得到了重复的结果。我们的模型非常基本: class LocationModel { public int LocationID { get; set; } public int ParentLocationID { get; set; } public string LocationName { get
class LocationModel
{
public int LocationID { get; set; }
public int ParentLocationID { get; set; }
public string LocationName { get; set;}
}
如果您将其与EF创建的实体进行比较,我只是删除了所有我们不需要/使用的字段(参见上面的链接)。因此,我修改了linq语句,改为使用此新模型:
DBEntities db = new DBEntities();
public IEnumerable<LocationModel> GetAllChildLocations(int parentId)
{
var locations = (from l in db.Locations
where l.ParentLocationID == parentId ||
l.LocationID == parentId
select new LocationModel()
{
LocationID = l.LocationID,
ParentLocationID = l.ParentLocationID,
LocationName = l.LocationName
}).ToList();
var children = locations.AsEnumerable()
.Union(db.Locations.AsEnumerable()
.Where(x => x.ParentLocationID == parentId)
.SelectMany(y => GetAllChildLocations(y.LocationID)))
.ToList();
return children.OrderBy(l => l.LocationName);
}
DBEntities db=newdbentities();
公共IEnumerable GetAllChildLocations(int parentId)
{
变量位置=(从数据库位置中的l开始
其中l.ParentLocationID==parentId||
l、 LocationID==父ID
选择新位置模型()
{
LocationID=l.LocationID,
ParentLocationID=l.ParentLocationID,
LocationName=l.LocationName
}).ToList();
var children=locations.AsEnumerable()
.Union(db.Locations.AsEnumerable()
.Where(x=>x.ParentLocationID==parentId)
.SelectMany(y=>GetAllChildLocations(y.LocationID)))
.ToList();
返回children.OrderBy(l=>l.LocationName);
}
当我在VisualStudio或LinqPad中运行它时,我现在得到了副本。以下是不产生重复项的原始代码:
public IEnumerable<Location> GetAllChildLocations(int parentId)
{
var locations = (from l in db.Locations
where l.ParentLocationID == parentId ||
l.LocationID == parentId
select l).ToList();
var child = locations.AsEnumerable()
.Union(db.Locations.AsEnumerable()
.Where(x => x.ParentLocationID == parentId)
.SelectMany(y => GetAllChildLocations(y.LocationID)))
.ToList();
return child;
}
public IEnumerable GetAllChildLocations(int-parentId)
{
变量位置=(从数据库位置中的l开始
其中l.ParentLocationID==parentId||
l、 LocationID==父ID
选择l).ToList();
var child=locations.AsEnumerable()
.Union(db.Locations.AsEnumerable()
.Where(x=>x.ParentLocationID==parentId)
.SelectMany(y=>GetAllChildLocations(y.LocationID)))
.ToList();
返回儿童;
}
为什么我使用自己的模型与EF生成的模型相比会产生重复?它是否与EF模型和我的模型没有的自动生成字段有关
为什么我使用自己的模型与EF生成的模型相比会产生重复
因为您使用的是Enumerable.Union
方法,默认情况下该方法使用引用相等。EFDbContext
change tracker在内部保留(跟踪)具有相同主键的已加载实体对象实例(即使您通过单独的数据库查询检索它们),因此引用相等有效。对于由查询select
操作符创建的newlocationmodel
实例,这是不可能的
解决此问题的一种方法是在LocationModel
类中实现GetHashCode
和Equals
。但总的来说,我不喜欢递归子对象检索的实现和Union
的使用-肯定有更好的方法,但这超出了这个问题的范围(但对于链接)
对我来说,邪恶的根源是以下情况
where l.ParentLocationID == parentId || l.LocationID == parentId
它同时选择项及其子项,导致结果集中出现重复项,然后应该通过Union
方法消除重复项。良好的实现根本不会生成重复项
为什么我使用自己的模型与EF生成的模型相比会产生重复
因为您使用的是Enumerable.Union
方法,默认情况下该方法使用引用相等。EFDbContext
change tracker在内部保留(跟踪)具有相同主键的已加载实体对象实例(即使您通过单独的数据库查询检索它们),因此引用相等有效。对于由查询select
操作符创建的newlocationmodel
实例,这是不可能的
解决此问题的一种方法是在LocationModel
类中实现GetHashCode
和Equals
。但总的来说,我不喜欢递归子对象检索的实现和Union
的使用-肯定有更好的方法,但这超出了这个问题的范围(但对于链接)
对我来说,邪恶的根源是以下情况
where l.ParentLocationID == parentId || l.LocationID == parentId
它同时选择项及其子项,导致结果集中出现重复项,然后应该通过Union
方法消除重复项。良好的实现根本不会生成重复项