【问题标题】:Convert Datasets to Generic List将数据集转换为通用列表
【发布时间】:2019-04-28 20:02:07
【问题描述】:

我有一个类属性如下

public class Country
{
   CountryId,
   CountryName,
   List<State>
}

Public class State
{
   StateId,
   StateName,
   List<City>
}

Public class City
{
   CityId,
   CityName
}

我有每个类的数据集,它们从数据库中提取数据如下。

CountryDS  
`````````  
CountryId | CountryName
1         | India  
2         | China  

StateDS  
```````  
CountryId | StateId | StateName  
1         | 1       | UP  
1         | 2       | MP  
1         | 3       | Punjab  
2         | 10      | Beijing  

CityDS  
``````  
StateId | CityId | CityName  
1       | 1      | Agra  
1       | 2      | Mathura  
2       | 5      | Ujjain  
2       | 7      | Dewas  
3       | 10     | Amritsar  

现在,我想将这些数据集转换为 List&lt;Country&gt; 对象,不使用嵌套循环或使用 LinQ 或快速提取数据的最佳方法。

Country  
--> CountryId  
    CountryName  
    State  
    --> StateId  
        StateName  
        City  
        --> CityId  
            CityName  

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 今天的google关键字是ORM
  • "没有嵌套循环或使用 LinQ 等" - 为什么要避免它们?
  • 我已经尝试过使用嵌套循环。但是创建对象需要很长时间,因为我有数百万的记录,因为 1 个国家可能有许多州,1 个州有许多城市。所以我想如果有办法用 Linq 做到这一点。那就帮帮我吧。

标签: c# list linq dataset


【解决方案1】:

...但是创建对象需要很长时间,因为我有数百万的记录,因为 1 个国家可能有许多州,1 个州有许多城市。所以我想如果有办法用 Linq 做到这一点。

请注意,LINQ 针对重用进行了优化,而不是针对快速代码。在内部,LINQ 将使用foreach,它将调用GetEnumerator()MoveNext()。专为您的解决方案设计的 foreach 可能会比 LINQ foreach 更快,并且您可以通过调用自己的枚举(GetEnumeratorMoveNext)进行更多优化。

不过,如果您想使用 LINQ,只要您想要带有子对象(通常带有外键)的对象,例如带有学生的学校、带有书籍的图书馆、带有州的国家,Enumerable.Groupjoin 就是路要走。

所以你有三个集合,使用主键和外键相互指向:

IEnumerable<Country> countries = ...
IEnumerable<State> states = ...
IEnumerable<City> cities = ...

你想要国家的集合,以及他们的州,每个州都有自己的城市。

var result = countries.GroupJoin(states,  // GroupJoin countries and states
   country => country.Id,                 // from the country take the primary key
   state => state.CountryId               // from the state take the foreign key
   (country, statesOfCountry) => new      // from every country with all its states
   {                                      // make one new object
       Id = country.Id,                   // cointaining only the properties you plan to use
       Name = country.Name,
       ...

       States = ...                       // see below
   }

为了计算States of every country with their cities,我们GroupjoinstatesOfCountry 集合与cities 集合,匹配主键和外键:

继续上面的 LINQ:

States = statesOfCountry.GroupJoin(cities,   // Groupjoin states with cities
   stateOfCountry => stateOfCountry.Id,      // from every state take the Id
   city => city.StateId,                     // from every city take the stateId
   (stateOfCountry, citiesOfState) => new    // again: when they match make a new object
   {
        // for performance: select only the properties yo actually plan to use
        Id = stateOfCountry.Id,
        Name = stateOfCountry.Name,

        // not needed: you know it equals Country.Id:
        // CountryId = stateOfCountry.CountryId,

        Cities = citiesOfState.Select(city => new
        {
             // only the properties you plan to use
             Id = city.Id,
             Name = city.Name,
             Location = city.Location,

             // not needed, you already know the value:
             // StateId = city.StateId,
        }),
   }

好消息是你只创建了一个可枚举的对象,也就是说:你只创建了一个知道如何枚举的东西。你还没有列举。这样做的好处是速度非常快,如果在枚举过程中您决定不需要某些信息,则不必枚举它。

例如,一旦你开始枚举并且你想忽略所有城市俄罗斯城市:

foreach (var country in result)
{
     if (country.Name != "Russia")
        ProcessCountry(country);
     // else: ignore

这样的好处是不会进行俄罗斯城市的GroupJoin

【讨论】:

  • 那么,嵌套的 foreach 会比 linq 运行得更快。?有没有其他方法可以做到这一点。?
  • 不,不是本身,LINQ 也使用嵌套的 foreach,所以这并不是让它更快的原因。但是,如果您编写自己的代码,则可以进行优化,例如设置列表的初始大小。此外:LINQ 只会在您请求元素时开始枚举。如果您不要求第三个元素,则不会计算此元素。如果您使用 foreach,您必须知道何时停止。如果您不知道,因为您的调用者决定何时停止,请创建一个返回 IEnumerable&lt;...&gt; 的函数,并在您的 foreach 中使用 yield return。这将防止计算比调用者要求的更多的项目。
  • 哦。知道了。感谢您的帮助和时间。
【解决方案2】:

在不使用 LinQ 或嵌套循环的情况下,您可以通过一个小解决方法来实现这一点。

  1. 将您的数据集转换为 JSON。
  2. 将 JSON 解析为适当的对象。

您可以使用 newtonsoft 进行序列化或反序列化。

【讨论】:

  • 我想在 c# 中使用这个对象,因为我必须提前处理这个对象。
猜你喜欢
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 2011-11-12
  • 2021-10-04
  • 2014-07-07
相关资源
最近更新 更多