到目前为止,我正在尝试创建一个根据特定条件进行分组的列表,然后在视图中显示该列表。
我有两个数据库表,一个是关联表。
第一张表
<?php if ( get_current_user_id() != 0 ) : ?>
第二张表(关联表)
public partial class InitialTraining
{
public InitialTraining()
{
InitialTrainingAssociations = new HashSet<InitialTrainingAssociation>();
}
public int Id { get; set; }
[ForeignKey("MedicInfo")]
public int TfoId { get; set; }
[ForeignKey("InstructorInfo")]
public int? InstructorId { get; set; }
[ForeignKey("PilotInfo")]
public int? PilotId { get; set; }
public DateTime DateTakenInitial { get; set; }
public decimal FlightTime { get; set; }
public bool Active { get; set; }
[StringLength(2000)]
public string Narrative { get; set; }
[Required]
[StringLength(20)]
public string TrainingType { get; set; }
[ForeignKey("CodePhase")]
public int PhaseId { get; set; }
[ForeignKey("PhaseTrainingType")]
public int PhaseTrainingTypeId { get; set; }
public string EnteredBy { get; set; }
public DateTime? EnteredDate { get; set; }
public virtual MedicInfo MedicInfo { get; set; }
public virtual MedicInfo InstructorInfo { get; set; }
public virtual MedicInfo PilotInfo { get; set; }
public virtual Code_Phase CodePhase { get; set; }
public virtual Code_PhaseTrainingType PhaseTrainingType { get; set; }
public virtual ICollection<InitialTrainingAssociation> InitialTrainingAssociations { get; set; }
}
这是我在C#中的public class InitialTrainingAssociation
{
public int Id { get; set; }
[ForeignKey("InitialTraining")]
public int InitialTrainingId { get; set; }
[ForeignKey("CodePerformanceAnchor")]
public int? PerformanceAnchorId { get; set; }
[ForeignKey("GradingSystem")]
public int? GradingSystemId { get; set; }
public virtual AviationMedicTraining.CodePerformanceAnchor CodePerformanceAnchor { get; set; }
public virtual InitialTraining InitialTraining { get; set; }
public virtual GradingSystem GradingSystem { get; set; }
}
。
GroupBy
我的目标
很明显,从我的代码中,我想按关联表中的性能锚点分组,但是我需要从// get list of initial training record ids for statistics
var lstInitialTrainings = db.InitialTrainings.Where(x => x.TfoId == medicId && x.Active).Select(x => x.Id).ToList();
// get list of initial training performance anchors associated with initial training records
var lstPerformanceAnchors = db.InitialTrainingAssociations
.Where(x => lstInitialTrainings.Contains(x.InitialTrainingId)).GroupBy(t => t.PerformanceAnchorId)
.Select(s => new MedicStatistic()
{
PerformanceAnchorName = db.CodePerformanceAnchor.FirstOrDefault(v => v.Id == s.Key).PerformanceAnchor,
AnchorCount = s.Count()
}).ToList();
表中获取更多信息,以将其包含在ViewModel Initial Training
中,但是我在确定时遇到了麻烦找出最好的方法。
我的总体目标是能够从MedicStatistic
表中获取性能锚定的最新时间。
视觉
初始培训表(并非所有片段均在摘录b / c中捕获,对于此问题而言,它们并不重要)
初始培训关联表
我期望的结果
因此,从上面提供的图片中可以看到,关联表中有多个Initial Training
用于性能锚点ID,但是它们各自具有不同的1
。因此,此特定性能锚已经完成了多次,但我需要从InitialTrainingId
表中获取最新日期。另外,我需要根据最近的日期从Initial Training
表中获取带有锚点的相应成绩。
因此,对于等于Grading System
的性能锚点。我想要与1
的{{1}}对应的等级,因为该记录是性能锚点最近的时间InitialTrainingId
中的内容已完成。
如果您有任何疑问,请告诉我。
答案 0 :(得分:2)
您希望按CodePerformanceAnchor
对数据进行分组,因此开始查询的最自然的方法是在其DbSet
处,这立即消除了分组的必要性:
from pa in db.CodePerformanceAnchors
let mostRecentInitialTraining
= pa.InitialTrainingAssociations
.Select(ita => ita.InitialTraining)
.OrderByDescending(tr => tr.DateTakenInitial)
.FirstOrDefault()
select new
{
pa.PerformanceAnchor,
mostRecentInitialTraining.DateTakenInitial,
mostRecentInitialTraining. ...
...
AnchorCount = pa.InitialTrainingAssociations.Count()
}
如您所见,仅使用导航属性,整个查询非常简单。我假设PerformanceAchor
类也有一个InitialTrainingAssociations
集合。
尽管我不能保证EF能够完全在服务器端执行它,但是对于更复杂的LINQ查询来说,这总是很棘手的事情。
答案 1 :(得分:1)
我将忽略您的virtual
类中的InitialTrainingAssociation
属性,因为您没有提及任何有关它们的内容,而且对于它们是否真正包含数据或为什么包含它们,我也不是很清楚是virtual
。
似乎IQueryable.Join
是合并所需数据的最简单方法。
在下面的示例中,我们将从InitialTrainings表中的条目开始。然后,我们将Join
与InitialTrainingAssociations表一起使用,这将导致成对的InitialTraining和InitialTrainingAssociation对象的集合。
var initialTrainingResults =
// Start with the InitialTrainings data.
db.InitialTrainings
// Add association information.
.Join(
// The table we want to join with
db.InitialTrainingAssociations,
// Key selector for the outer type (the type of the collection
// initiating the join, in this case InitialTraining)
it => it.Id,
// Key selector for the inner type (the type of the collection
// being joined with, in this case InitialTrainingAssociation)
ita => ita.InitialTrainingId,
// Result selector. This defines how we store the joined data.
// We store the results in an anonymous type, so that we can
// use the intermediate data without having to declare a new class.
(InitialTraining, InitialTrainingAssociation) =>
new { InitialTraining, InitialTrainingAssociation }
)
从这里,我们可以通过执行更多Join
来添加PerformanceAnchors和GradingSystems表中的数据。每次执行Join
时,都会向匿名类型添加一个新实体。结果将是匿名类型的集合,这些匿名类型表示我们从数据库中检索到的数据。
// Add performance anchor information.
.Join(
db.PerformanceAnchors,
x => x.InitialTrainingAssociation.PerformanceAnchorId,
pa => pa.Id,
(x, PerformanceAnchor) =>
new { x.InitialTrainingAssociation, x.InitialTraining, PerformanceAnchor }
)
// Add grading system information.
.Join(
db.GradingSystems,
x => x.InitialTrainingAssociation.GradingSystemId,
gs => gs.Id,
// No need for InitialTrainingAssociation anymore, so we don't
// include it in this final selector.
(x, GradingSystem) =>
new { x.InitialTraining, x.PerformanceAnchor, GradingSystem }
);
(这是一个冗长的示例,展示了如何将所有表连接在一起。如果不需要一次访问所有数据,则可以使用较少的Joins,并且可以过滤InitialTrainings集合首先,如果您知道您只需要访问某些数据。)
这时,initialTrainingResults
是一个IEnumerable
,其中包含InitialTrainings,PerformanceAnchors和GradingSystems表之间每个关联的一个条目。本质上,我们所做的就是获取所有InitialTrainingAssociations并将其ID扩展为实际对象。
要获取每个性能锚点的最新数据集:
var performanceAnchors = initialTrainingResults
// Group by each unique Performance Anchor. Remember, the IEnumerable
// we are operating on contains our anonymous type of combined Training,
// Performance Anchor and Grading data.
.GroupBy(x => x.PerformanceAnchor.Id)
// Order each Performance Anchor group by the dates of its training,
// and take the first one from each group
.Select(g => g.OrderByDescending(x => x.InitialTraining.DateTakenInitial).First());
答案 2 :(得分:0)
在Select
中,您可以命令分组结果以InitialTraining
的形式获取最新的关联DateTakenInitial
,然后从中获取所需的数据
//...omitted for brevity
.GroupBy(t => t.PerformanceAnchorId)
.Select(g => {
var mostRecent = g.OrderByDescending(_ => _.InitialTraining.DateTakenInitial).First();
// get the corresponding grade with the anchor from the Grading System table
var gradeid = mostRecent.GradingSystemId;
var gradingSystem = mostRecent.GradingSystem;
//get the most recent date from the Initial Training
var mostRecentDate = mostRecent.InitialTraining.DateTakenInitial
//..get the desired values and assign to view model
var model = new MedicStatistic {
//Already have access to CodePerformanceAnchor
PerformanceAnchorName = mostRecent.CodePerformanceAnchor.PerformanceAnchor
AnchorCount = g.Count(),
MostRecentlyCompleted = mostRecentDate,
};
return model;
});