我有三個相互關聯的表。我在entityframwork中搜索了groupBy方法,但沒有得到正確的答案。這是表:
public class DayProgramOffice
{
public long Id { get; set; }
public DateTime Day { get; set; }
public virtual ICollection< ScheduleOffice> ScheduleOffices { get; set; }
}
public class ScheduleOfficepublic long Id { get; set; }
public DateTime Time { get; set; }
public virtual DayProgramOffice DayProgramOffice { get; set; }
public long DayProgramOfficeId { get; set; }
public virtual TypeConsultaion TypeConsultaion { get; set; }
public long TypeConsultaionId { get; set; }
}
public class TypeConsultaionpublic byte Id { get; set; }
public string TypeName { get; set; }
public virtual ICollection< ScheduleOffice> ScheduleOffices { get; set; }
并且有三個viewmodel想要發送資料給它:
public class Day
{
public DateTime day { get; set; }
public IList<TypeConViewModel> Types{ get; set; }
}
public class TypeConViewModel
{
public string TypeName { get; set; }
public IList<HoverViewModel> Hovers { get; set; }
}
public class HoverViewModel
{
public DateTime Hover { get; set; }
在視圖中我想顯示這樣的資料:
(var item1 in Model. Days)
{
<p>@item1.Day</p>
foreach (var item2 in item1.Types)
{
<p>@item2.TypeName</p>
foreach (var item3 in item2.Hover)
{
<p>@item3.hover</p>
}
}
}
我使用這段代碼,但無法對資料進行分組:
_db.DayProgramOffice
.Include(c=>c.ScheduleOffice)
.ThenInclude(d=>d.TypeConsultaion)
.ToList()。
uj5u.com熱心網友回復:
通過這種方式分組,但你可以通過改變表的結構來提高查詢的性能!
控制器或動作。
控制器或動作 :
public IActionResult Index()
{
var daysModel = _db.ScheduleOffices.
.Include(a => a.DayProgramOffice)
.Include(b => b.TypeConsultaion)
.ToList()
.GroupBy(d => d.DayProgramOffice)
.Select(d => new Day)
{
day = d.Key.Day,
Types = d.GroupBy(x => x.TypeConsultaion) 。 Select(span class="hljs-params">f => new TypeConViewModel{
TypeName = f.Key.TypeName,
Hovers = f.Key.TypeName. Select(span class="hljs-params">g => new HoverViewModel {
Hover = g.Time.
}).ToList()
}).ToList()
})
.ToList()。
return View(dayModel);
在你的視圖中,你有一些錯誤,把它改成這樣 :
@foreach (var item1 in Model){
<p class="day">/span>@item1. day</p>@item1.
foreach (var item2 in item1.Types){
<p class="type">@item2. TypeName</p>
foreach (var item3 in item2.Hovers)
{
<p class="hover">@item3. Hover</p>@item3.
}
}
}
uj5u.com熱心網友回復:
所以你有一個DayProgramOffices的表,和一個ScheduleOffices的表。在DayProgramOffices和ScheduleOffices之間有一個一對多的關系:每個DayProgramOffice都有0個或更多的ScheduleOffices,每個ScheduleOffice正好屬于一個DayProgramOffice,即外鍵所指的DayProgramOffice。
類似地,在TypeConsultations和ScheduleOffices之間有一個一多的關系:每個TypeConsultation有零個或多個ScheduleOfficess,每個ScheduleOffice正好屬于一個TypeConsultation,即外鍵所指向的那個。
唉,你給了我們一些代碼,但這些代碼并不是你想要的,而且你忘了精確地說明你想要什么。然而,從你的代碼中,我認為你想要的是:
要求:從每個DayProgramOffice中給我所有它的零個或多個ScheduledOffices,以及這個ScheduledOffice的TypeConsultation。
簡單的方法:使用虛擬ICollection
。當使用物體框架連接表時,最簡單的解決方案通常是使用虛擬ICollections。物體框架知道你的關系,并且可以將其轉換為適當的(Group-)Join。
使用(var dbContext = new OfficeDbContext(...))
{
var dayProgramOffices = dbContext.DayProgramOffices。 Select(dayProgramOffice => new)
{
//選擇你打算使用的DayProgramOffice屬性:
Id = dayProgramOffice.Id。
Day = dayProgramOffice.Day。
...
//獲取此dayProgramOffice的所有ScheduledOffices。
ScheduledOffices = dayProgramOffice.ScheduledOffices。
.Select(scheduleOffice => new)
{
//只選擇你打算使用的屬性:
Id = scheduledOffice.Id,
...
//不要選擇外鍵,你已經知道這個值了。
//DayProgramOfficeId = scheduledOffice.DayProgramOfficeId,/span>
//這個ScheduledOffice正好有一個TypeConsultation:。
TypeConsultation = new
{
Id = scheduledOffice.TypeConsultation.Id,
TypeName = scheduledOffice.TypeConsultation.TypeName。
...
}
})
.ToList()。
});
我選擇了創建匿名型別(new {...}),以防止將不使用的值從資料庫管理系統轉移到你的本地行程。這也將使你能夠自由地添加不在表中的屬性,例如,辦公室被安排的最早時間:
DayProgramOffices。 Select(dayProgramOffice => new。
{
...
NewestScheduledOfficeTime = dayProgramOffice.ScheduledOffices
.Select(scheduledOffice => scheduledOffice.Time)
.Min()。
當然,如果你愿意,你可以指定你想把你獲取的資料放在哪種型別中。
替代方法:使用外鍵
var dayProgramOffices = dbContext.DayProgramOffices. Select(dayProgramOffice => new)
{
Id = dayProgramOffice.Id。
Day = dayProgramOffice.Day。
...
//使用外鍵獲取此dayProgramOffice的所有ScheduledOffices。
ScheduledOffices = dbContext.ScheduledOffices。
.Where( scheduledOffice.DayProgramOfficeId == dayProgramOffice.Id)
.Select(scheduleOffice => new)
{
Id = scheduledOffice.Id。
...
//使用外鍵來獲取這個ScheduledOffice的TypeConsultation。
TypeConsultation = dbContext.TypeConsultations。
.Where(typeConsultation => typeConsulation。 Id == scheduledOffice.TypeConfulstionId)
.Select(typeConsulation => new)
{
Id = typeConsultation.Id,
TypeName = typeConsultation.TypeName。
...
})
//期望正好有一個這樣的TypeConsultation:。
.SingleOrDefault()。
})
.ToList()。
});
這可能是你的物體框架版本不允許SingleOrDefault。當然,你也可以使用FirstOrDefault。這甚至可能是更有效的,因為沒有檢查唯一性。
困難的方法:自己做(Group-)Joins
。Entity框架將把前面方法中的運算式翻譯成(Group-)Joins。當然,你也可以自己來做這些GroupJoins:
var dayProgramOffices = dbContext.DayProgramOffices.GroupJoin(
dbContext.ScheduledOffices。
dayProgramOffice => dayProgramOffice.Id, // take the primary key。
scheduledOffice => scheduledOffice.DayProgramOfficeId, //取外鍵。
//引數resultSelector:對于每一個dayProgramOffice和所有0或更多。
// scheduledOffices that have a foreign key that refers to this dayProgramOffice。
//make one new:
(dayProgramOffice, scheduledOffices) => new
{
Id = dayProgramOffice.Id,
Day = dayProgramOffice.Day,
//要獲得每個ScheduledOffice的唯一的TypeConsultaition,做一個Join。
ScheduledOffices = scheduledOffices.Join(
dbContext.TypeConsultations,
scheduledOffice => scheduledOffice.TypeConsultationId, //外鍵.
typeConsultation => typeConsultation.Id, //主鍵
//引數resultSelector:對于每一個預定的辦公室,與它的一個。
(scheduledOffice, typeConsultation) =>/span> new
{
Id = scheduledOffice.Id。
...
TypeConsultation = new.
{
Id = typeConsultation.Id,
TypeName = typeConsultation.TypeName。
...
}),
})
.ToList()。
});
如果你有一個一對多的關系,并且你想要 "專案與它們的子專案",從 "一 "邊開始,并使用一個
GroupJoin。如果你想讓子專案與外鍵所指的唯一的父專案在一起,使用Join。
為什么你不應該使用Include
?你的Dbcontext有一個ChangeTracker。如果你查詢一個物件而不使用Select,那么該表的完整行將被轉移。
除了這可能會轉移你不打算使用的屬性之外,該物件也被放入ChangeTracker中,同時還有該物件的一個副本。你將獲得對該副本的參考(也可能是原件,這并不重要,理論上是一樣的)。每當你對獲取的物件進行修改,那么事實上你就是在改變ChangeTracker中的副本。
如果你呼叫DbContext.SaveChanges,那么原始物件的每個屬性都會與副本進行價值比較。如果它們不相等,那么改變的值將在資料庫中被更新。
如果您不打算更改獲取的物件,這將是對處理能力的極大浪費。
當使用物體框架從資料庫中獲取資料時,請始終使用
Select,并且只選擇您實際打算使用的屬性。只獲取完整的物件,如果你打算改變獲取的資料,只使用Include/ThenInclude。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/310097.html
標籤:
上一篇:不能將型別'System.Collections.Generic.IEnumerable<string>'隱式轉換為'string'。
下一篇:如何選擇默認的輸入鍵盤?

