기본 엔터티의 공통 식별자로 엔터티 목록을 그룹화하고 각 그룹의 첫 번째 엔터티를 선택한 다음 새 엔터티 목록을 반환하고 싶습니다. 관련된 세 가지 엔터티가 있습니다 : 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
ov2에 종속 된 모든 ObjectVersion을 얻으려면 :
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
GenericObject가 다른 ov2에 종속 된 최신 ObjectVersion을 얻으려면 :
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
다음 출력을 얻기 위해 필터링은 어떻게 생겼습니까? 기본적으로 GenericObject가 다른 ov2를 포함하는 최신 ObjectDependencies를 얻고 싶습니다. 필터링은 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
어떤 도움이라도 대단히 감사하겠습니다!
편집하다:
Jason Boyd의 답변을 기반으로 LINQ to 엔터티를 지원하는 다음 솔루션을 사용하게되었습니다. 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
그래서 LINQ 쿼리를 확장 메서드로 리팩토링 할 수있는 자유를 얻었습니다. 그러면 진행 상황을 더 쉽게 따라갈 수 있습니다.
public static class Extensions
{
public static IQueryable<ObjectDependency> WhereContainsObjectVersion(this IQueryable<ObjectDependency> source, int objectVersionId)
{
return
source
.Where(x => x.ObjectVersion1.Id == objectVersionId || x.ObjectVersion2.Id == objectVersionId);
}
public static IQueryable<ObjectVersion> SelectDependentObjectVersions(this IQueryable<ObjectDependency> source, int objectVersionId)
{
return
source
.WhereContainsObjectVersion(objectVersionId)
.Select(x => x.ObjectVersion1.Id == objectVersionId ? x.ObjectVersion2 : x.ObjectVersion1);
}
public static IQueryable<TResult> SelectDependentObjectVersions<TResult>(this IQueryable<ObjectDependency> source, int objectVersionId, Func<ObjectDependency, ObjectVersion, TResult> selector)
{
return
source
.WhereContainsObjectVersion(objectVersionId)
.Select(x => x.ObjectVersion1.Id == objectVersionId ? selector(x, x.ObjectVersion2) : selector(x, x.ObjectVersion1));
}
public static IQueryable<ObjectVersion> SelectByLatestDistinctGenericObject(this IQueryable<ObjectVersion> source)
{
return
source
.GroupBy(x => x.GenericObject.Id)
.Select(x => x.OrderByDescending(y => y.Id).FirstOrDefault());
}
public static IQueryable<ObjectDependency> SelectByLatestDistinctGenericObject(this IQueryable<ObjectDependency> source, int objectVersionId)
{
return
source
.SelectDependentObjectVersions(objectVersionId, (x, y) => new { ObjectDependency = x, ObjectVersion = y })
.GroupBy(x => x.ObjectVersion.GenericObject.Id)
.Select(x => x.OrderByDescending(y => y.ObjectVersion.Id).FirstOrDefault())
.Select(x => x.ObjectDependency);
}
}
그런 다음 다음과 같은 방법으로 호출 할 수 있습니다 (LINQ 쿼리의 일부를 주석 처리하고 확장 메서드가 대체하는 각 쿼리의 부분을 확인할 수 있도록 확장 메서드를 삽입했습니다).
// Get all ObjectDependencies containing ov2
// Output:
// d1
// d2
// d3
Console.WriteLine("Get all ObjectDependencies containing ov2");
IEnumerable<ObjectDependency> ov2Dependencies =
dependencies
//.Where(d => d.ObjectVersion1.Id == ov2.Id || d.ObjectVersion2.Id == ov2.Id)
.WhereContainsObjectVersion(ov2.Id)
.OrderBy(d => d.Name);
foreach (ObjectDependency dependency in ov2Dependencies)
{
Console.WriteLine(dependency.Name);
}
// Get all ObjectVersions dependent on ov2
// Output:
// 1
// 3
// 4
Console.WriteLine("Get all ObjectVersions dependent on ov2");
IEnumerable<ObjectVersion> 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)
.SelectDependentObjectVersions(ov2.Id)
.OrderBy(o => o.Id);
foreach (ObjectVersion ov in ov2AllDependentObjectVersions)
{
Console.WriteLine(ov.Id);
}
// Get newest ObjectVersions dependent on ov2 with different GenericObject
// Output:
// 3
// 4
Console.WriteLine("Get newest ObjectVersions dependent on ov2 with different GenericObject");
IEnumerable<ObjectVersion> ov2NewestDependentObjectVersions =
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())
.SelectDependentObjectVersions(ov2.Id)
.SelectByLatestDistinctGenericObject()
.OrderBy(o => o.Id);
foreach (ObjectVersion ov in ov2NewestDependentObjectVersions)
{
Console.WriteLine(ov.Id);
}
// Get newest ObjectDependencies containing ov2 with different GenericObject
// Output:
// d2
// d3
Console.WriteLine("Get newest ObjectDependencies containing ov2 with different GenericObject");
IEnumerable<ObjectDependency> ov2NewestDependencies =
dependencies
//.Where(d => d.ObjectVersion1.Id == ov2.Id || d.ObjectVersion2.Id == ov2.Id)
// ???
.SelectByLatestDistinctGenericObject(ov2.Id)
.OrderBy(d => d.Name);
foreach (ObjectDependency dependency in ov2NewestDependencies)
{
Console.WriteLine(dependency.Name);
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다