我可以使用一些幫助來確定從SQL數據庫中檢索父子對象的最佳(最高性能/易維護)策略。父子表的SQL策略
我繼承了這段代碼,而且我已經有了相對較短的截止日期,我希望儘可能少做基礎性更改。我有足夠的時間在下一個螺旋上實現nhibernate或其他ORM,我現在不能這樣做。我以最少的修改時間在最短的時間內尋找最好的事情。
扭曲的是,有不同的兒童類型(實現一個普通的兒童界面)。
例如,
家長:VehicleFleet(包含車隊名稱,經理姓名,車輛列表)
兒童:IVehicle(包括製造商,型號,位置等)
但是,可能有多個車輛類型 - 例如汽車,廂式車,摩托車 - 各具有不同的屬性/列。有一個獨立的汽車,麪包車和摩托車。可能有也可能沒有VehicleBase表,其中包含適用於任何車輛的列。
返回多個VehicleFleet對象的最佳策略是什麼,每個對象都有相關的Vehicle子對象?
這裏有一對夫婦的戰略我已經試過(僞代碼提交) -
假設:
所有的getXXXX功能使用DataReader場景
方法1落後:簡單&慢 - 這是做的最糟糕的方式,原因很明顯
IEnumerable<Fleet> GetFleetsAndVehicles() {
foreach (var fleet in myFleetDao.GetAllFleets()) {
foreach (var vehicleTypeDao in myVehicleTypeDaos)
fleet.Vehicles.Add (vehicleTypeDao.GetVehicles (fleet.Id);
yield return fleet;
}
yield break;
}
方法2:預取兒童
IEnumerable<Fleet> GetFleetsAndVehicles() {
var allVehicles = (from vtd in myVehicleTypeDaos
from v in vtd.GetAllVehicles()
select v).ToLookup (v => v.FleetId);
foreach (var fleet in myFleetDao.GetAllFleets())
{
fleet.Vehicles = allVehicles[fleet.Id].ToList();
yield return fleet;
}
yield break;
}
方法3:預取兒童,兒童附加異步地
IEnumerable<Fleet> GetFleetsAndVehicles() {
foreach (var fleet in new AsyncGetter.GetFleetsAndVehicles())
yield return fleet;
yield break;
}
class AsyncGetter
{
// left out instance variables, Auto/Manual Reset Events, locking, etc. for brevity
IEnumerable<Fleet> GetFleetsAndVehicles()
{
StartAsyncStuff();
while (myUnconsumedFleets.Count > 0)
{
yield return myUnconsumedFleets.Remove (0);
WaitUntilMoreFleetsAreAdded();
}
yield break;
}
void StartAsyncStuff()
{
myAllVehicles = <same as method 2>
foreach (var fleet in myFleetDao.GetAllFleets())
{
AttachVehiclesAsync (fleet);
}
}
void AttachVehiclesAsync (Fleet f)
{
// assume using ThreadPool.QueueUserWorkItem right now
WaitForAllVehiclesToLoad();
f.Vehicles = myAllVehicles[f.Id].ToList();
myUnconsumedFleets.Add (f);
}
}
方法4:交錯的父/子查詢
IEnumerable<Fleet> GetFleetsAndVehicles() {
var allVehicles = from vtd in myVehicleTypeDaos
from v in vtd.GetAllVehicles()
orderby v.FleetId
select v;
var allVehiclesEnumerator = allVehicles.GetEnumerator();
foreach (var fleet in myFleetDao.GetAllFleets())
{
fleet.Vehicles = GetAllChildVehiclesAndMaintainEnumeratorPosition (allVehiclesEnumerator, fleet);
yield return fleet;
}
}
到目前爲止,使用一些測試數據,我看到那個方法3是最高性能的(快於下一個最佳速度27%),而方法1是最差的(比方法1慢4倍)。
所以,如果你有建議,我很樂意聽到他們!
如果您可以自由選擇單個表繼承模型,而不是在LINQ2SQL中內置支持,請參閱http://msdn.microsoft.com/en-us/library/bb399352.aspx和http:// msdn。 microsoft.com/en-us/library/bb386919.aspx – 2010-08-28 07:14:01