我想通過其基本實體的公共標識符對實體列表進行分組,選擇每個組的第一個實體並返回實體的新列表。有3個不同的實體參與:GenericObject,ObjectVersion和ObjectDependency。基於其基本實體的公共標識符過濾相關實體
public class GenericObject
{
public int Id { get; set; }
}
public class ObjectVersion
{
public int Id { get; set; }
public GenericObject GenericObject { get; set; }
}
public class ObjectDependency
{
public string Name { get; set; }
public ObjectVersion ObjectVersion1 { get; set; }
public ObjectVersion ObjectVersion2 { get; set; }
}
樣本設置是這樣的:
GenericObject go1 = new GenericObject { Id = 1 };
GenericObject go2 = new GenericObject { Id = 2 };
GenericObject go3 = new GenericObject { Id = 3 };
ObjectVersion ov1 = new ObjectVersion { Id = 1, GenericObject = go1 };
ObjectVersion ov2 = new ObjectVersion { Id = 2, GenericObject = go2 };
ObjectVersion ov3 = new ObjectVersion { Id = 3, GenericObject = go3 };
ObjectVersion ov4 = new ObjectVersion { Id = 4, GenericObject = go1 };
List<ObjectDependency> dependencies = new List<ObjectDependency>
{
new ObjectDependency { Name = "d1", ObjectVersion1 = ov1, ObjectVersion2 = ov2 },
new ObjectDependency { Name = "d2", ObjectVersion1 = ov2, ObjectVersion2 = ov3 },
new ObjectDependency { Name = "d3", ObjectVersion1 = ov4, ObjectVersion2 = ov2 }
};
爲了得到含OV2所有ObjectDependencies,我會過濾這樣的:
var ov2Dependencies = dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.OrderBy(d => d.Name);
foreach (ObjectDependency dependency in ov2Dependencies)
{
Console.WriteLine(dependency.Name);
}
// Output:
// d1
// d2
// d3
爲了讓所有ObjectVersions依賴在ov2上:
var ov2AllDependentObjectVersions =
dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.Select(d => d.ObjectVersion1)
.Union(dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.Select(d => d.ObjectVersion2))
.Where(o => o.Id != ov2.Id)
.OrderBy(o => o.Id);
foreach (ObjectVersion ov in ov2AllDependentObjectVersions)
{
Console.WriteLine(ov.Id);
}
// Output:
// 1
// 3
// 4
爲了獲得最新的ObjectVersions依賴OV2不同GenericObject:
var ov2LatestDependentObjectVersions =
dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.Select(d => d.ObjectVersion1)
.Union(dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.Select(d => d.ObjectVersion2))
.Where(o => o.Id != ov2.Id)
.GroupBy(o => o.GenericObject.Id)
.Select(g => g.OrderByDescending(o => o.Id).FirstOrDefault())
.OrderBy(o => o.Id);
foreach (ObjectVersion ov in ov2LatestDependentObjectVersions)
{
Console.WriteLine(ov.Id);
}
// Output:
// 3
// 4
如何將過濾的樣子,以達到以下輸出?基本上,我想獲得最新的ObjectDependencies,其中包含具有不同GenericObject的ov2。過濾應該通過使用IQueryable直接轉換成T-SQL。
var ov2LatestDependencies = dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
// ???
.OrderBy(d => d.Name);
foreach (ObjectDependency dependency in ov2LatestDependencies)
{
Console.WriteLine(dependency.Name);
}
// Output:
// d2
// d3
我創建了一個小提琴這裏:https://dotnetfiddle.net/OZQlWO
任何幫助,將不勝感激!
編輯:
我結束了使用基於傑森·博伊德的答案如下解決方案,支持LINQ到實體:https://dotnetfiddle.net/YSj8ki
var ov2LatestDependencies = dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.Where(x => x.ObjectVersion1.Id == ov2.Id)
.Select(x => new
{
ObjectDependency = x,
ObjectVersion = x.ObjectVersion2
})
.Union(
dependencies.Where(d => d.ObjectVersion1.Id == ov2.Id
|| d.ObjectVersion2.Id == ov2.Id)
.Where(x => x.ObjectVersion2.Id == ov2.Id)
.Select(x => new
{
ObjectDependency = x,
ObjectVersion = x.ObjectVersion1
})
)
.GroupBy(x => x.ObjectVersion.GenericObject.Id)
.Select(x => x.OrderByDescending(y => y.ObjectVersion.Id).FirstOrDefault())
.Select(x => x.ObjectDependency)
.OrderBy(d => d.Name);
foreach (ObjectDependency dependency in ov2LatestDependencies)
{
Console.WriteLine(dependency.Name);
}
// Output:
// d2
// d3
這看起來很有希望,但我認爲這不會很好地轉化爲IQueryable/T-SQL? – niklr
我錯過了'iqueryable'標籤。無論如何,我認爲這不重要。我相當肯定,你可以將所有'IEnumerable'類型更改爲'IQueryable'(參數和返回類型),它應該可以正常工作。 –
@nilr - 根據新信息更新答案。用'IQueryable'替換了所有'IEnumerable'並刪除了迭代器塊。我相信這應該適合你。 –