Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 父子表的SQL策略_C#_Sql_Linq_Query Optimization - Fatal编程技术网

C# 父子表的SQL策略

C# 父子表的SQL策略,c#,sql,linq,query-optimization,C#,Sql,Linq,Query Optimization,我需要一些帮助来确定从SQL数据库检索父子对象的最佳(性能最好/易于维护)策略 我继承了这段代码,在这方面我有一个相对较短的期限,我想做尽可能少的基础性修改。我有足够的时间在下一个螺旋中实现nhibernate或其他ORM,我现在做不到。我正在寻找在最短的时间内用最少的修改量做最好的事情 问题在于有不同的子类型(实现了一个通用的子接口) 例如, 父项:VehicleFleet(包含车队名称、经理姓名、车辆列表) 子项:iHicle(包含品牌、型号、位置等) 但是,IVehicle可能有多种类型,

我需要一些帮助来确定从SQL数据库检索父子对象的最佳(性能最好/易于维护)策略

我继承了这段代码,在这方面我有一个相对较短的期限,我想做尽可能少的基础性修改。我有足够的时间在下一个螺旋中实现nhibernate或其他ORM,我现在做不到。我正在寻找在最短的时间内用最少的修改量做最好的事情

问题在于有不同的子类型(实现了一个通用的子接口)

例如,
父项:VehicleFleet(包含车队名称、经理姓名、车辆列表)
子项:iHicle(包含品牌、型号、位置等)

但是,IVehicle可能有多种类型,如汽车、面包车、摩托车,每种类型都有不同的属性/列。有一张单独的桌子,可以放汽车、面包车和摩托车。可能有也可能没有包含适用于任何IVehicle的列的VehicleBase表

返回多个VehicleFleet对象及其相关车辆子对象的最佳策略是什么

以下是我尝试过的几种策略(用伪代码表示)-

假设:
所有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;
}
IEnumerable GetFleetsAndVehicles(){
foreach(myFleetDao.GetAllFleets()中的var fleet){
foreach(myVehicleTypeDaos中的var vehicleTypeDao)
fleet.Vehicles.Add(vehicleTypeDao.GetVehicles(fleet.Id));
产量回收车队;
}
屈服断裂;
}
方法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;
}
IEnumerable GetFleetsAndVehicles(){
var allVehicles=(来自myVehicleTypeDaos中的vtd
从vtd.GetAllVehicles()中的v开始
选择v.ToLookup(v=>v.FleetId);
foreach(myFleetDao.GetAllFleets()中的var fleet)
{
fleet.Vehicles=allVehicles[fleet.Id].ToList();
产量回收车队;
}
屈服断裂;
}
方法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);
 }
}
IEnumerable GetFleetsAndVehicles(){
foreach(新AsyncGetter.GetFleetsAndVehicles()中的var车队)
产量回收车队;
屈服断裂;
}
类异步获取程序
{
//为简洁起见,省略了实例变量、自动/手动重置事件、锁定等
IEnumerable GetFleets和Vehicles()
{
StartAsyncStuff();
而(MyUnumedFleets.Count>0)
{
收益返回MyUnumedFoets.Remove(0);
waituntilmorefleetsreaded();
}
屈服断裂;
}
void StartAsyncStuff()
{
myAllVehicles=
foreach(myFleetDao.GetAllFleets()中的var fleet)
{
附件车辆异步(车队);
}
}
无效附加车辆异步(车队f)
{
//假设现在正在使用ThreadPool.QueueUserWorkItem
waitforallvehiclestolad();
f、 Vehicles=myAllVehicles[f.Id].ToList();
我的未消耗量。添加(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;
 }
}
IEnumerable GetFleetsAndVehicles(){
var allVehicles=来自myVehicleTypeDaos中的vtd
从vtd.GetAllVehicles()中的v开始
orderby v.FleetId
选择v;
var allvehiclessEnumerator=allVehicles.GetEnumerator();
foreach(myFleetDao.GetAllFleets()中的var fleet)
{
fleet.Vehicles=GetAllChildVehicles和MaintainEnumeratorPosition(所有车辆枚举器,车队);
产量回收车队;
}
}
到目前为止,使用一些测试数据,我发现方法3的性能最好(比次优快27%),而方法1的性能最差(比方法1慢4倍)


因此,如果你有什么建议,我很乐意听听!

冒着没有为当前问题提供有用答案而被否决的风险,我仍然需要说:。当然,可能仍有一些用例确实需要执行一些自定义数据读取器魔术。将继承层次结构从数据库映射到对象模式但我通常不是他们中的一员

有很多ORM可以为您解决这个问题。它被称为“每类型表继承映射”。任何合适的ORM都支持这一点,并允许您急切地获取父/子关系

如果性能确实是一个很大的问题(是吗?),那么您可能会通过切换到“单表继承”策略(所有类型都在一个单表中,带有一个鉴别器列)获得最大的收益

实体框架和NHibernate都支持单表和每种类型表的开箱即用。Linq 2 SQL(好的,可能不是完整的ORM)只支持单表继承;正如@Albin Sunnanbo所说,如果您可以更改数据库模式,这可能是一种选择。还有许多其他ORM值得研究


在这里,这是我的心血来潮;-),希望能有所帮助。

我认为如果您首先获得所有需要选择的车队的所有车辆,并且在获得结果时填充车队对象,这将是最快的


现在您肯定已经解决了这个问题,哪一个是最好的?

如果您可以自由选择单表继承模型,而不是LINQ2SQL中内置的支持,请参阅,这是一个完全可以接受的答案。。。但不是现在。我继承了一个项目,在这方面我有一个相对接近的最后期限,我想做尽可能少的基础性改变。我有足够的时间在下一个螺旋中实现nhibernate,我现在做不到。我正在寻找在最短的时间内用最少的修改量做最好的事情。