c# - 使用 LINQ 到具有集合属性的实体的最佳方式

标签 c# linq entity-framework

假设我有以下模型:

Cities and Trainstations

如您所见,每个城市都有一个或多个火车站。

我有以下类型:

public class CityDTO
{
    public string CityName { get; set; }
    public string StateName { get; set; }
    public List<string> Trainstations { get; set; }
}

现在 LINQ 最棒的地方在于我可以查询 Entity Framework 并返回我的类型的新集合:

    public List<CityDTO> GetCities()
    {
        using (var db = new CityDataContext())
        {

            var cities = db.Cities;
            var trainstations = db.TrainStations;

            var query =
            (from city in cities
             select new CityDTO
             {
                 CityName = city.Name,
                 StateName = city.State

             }).ToList();

            return query;
        }
    }

问题是:我还可以在同一个 LINQ 查询中返回火车站名称的集合以添加到我的 CityDTO 类吗?

   public List<CityDTO> GetCities()
    {
        using (var db = new CityDataContext())
        {

            var cities = db.Cities;
            var trainstations = db.TrainStations;

            var query =
            (from city in cities
             join trainstation in trainstations
             on city.CityId
             equals trainstation.CityId into orderGroup
             select new CityDTO
             {
                 CityName = city.Name,
                 StateName = city.State
                 //assign List<string> of trainstation names to CityDTO.Trainstations

             }).ToList();

            return query;
        }
    }

上面的 Join 的另一个问题是它会多次返回相同的城市名称(对于它的每个火车站),而我只希望每个城市有一个 CityDTO 实例。

这最好用两个 LINQ 语句来完成吗?一个获取新的城市列表,第二个获取每个城市的火车站列表?

最佳答案

@haim770,你的回答帮助我走上了正轨。出于兴趣,我不得不再更改两件事。

当我刚刚添加 Select projector 时,出现以下运行时错误

enter image description here

所以 Select 期望投影类型是 IEnumerable,所以我可以这样做,一切都会很酷:

public class CityDTO
{
    public string CityName { get; set; }
    public string StateName { get; set; }
    public IEnumerable<string> Trainstations { get; set; } //changed from List<> to IEnumerable<> 
}

现在一切正常:

    public List<CityDTO> GetCities()
    {
        using (var db = new CitysDataEntities())
        {
            var cities = db.Cities;

            var query =
            (from city in cities
             select new CityDTO
                 {
                    CityName = city.Name,
                    Trainstations = city.TrainStations.Select(ts => ts.Name)  //now this works

                 }).ToList();

            return query;
        }
    }

然而,在进一步阅读之后,我决定使用 IQueryable,它也有一个 Select 方法。

这是因为 IQueryable.Select 在 System.Linq 下,而 IEnumerable.Select 在 System.Collections Namespace 下。这一点很重要,因为 IQueryable.Select 经过优化,可以在服务器上执行所有筛选器并仅将结果返回给客户端,而 IEnumerable.Select 在筛选前首先将对象加载到客户端。

IEnumerable Vs IQueryable

所以结果是这样的

public class CityDTO
{
    public string CityName { get; set; }
    public string StateName { get; set; }
    public IQueryable<string> Trainstations { get; set; } // changed to IQueryable
}

    public List<CityDTO> GetCities()
    {
        using (var db = new CitysDataEntities())
        {
            var cities = db.Cities;

            var query =
            (from city in cities
             select new CityDTO
                 {
                    CityName = city.Name,
                     Trainstations = city.TrainStations.Select(ts => ts.Name).AsQueryable() // return AsQueryable

                 }).ToList();

            return query;
        }
    }

现在,当我添加过滤器时,它们将在服务器端应用。

MSDN - Queryable.Select

MSDN - Enumerable.Select

关于c# - 使用 LINQ 到具有集合属性的实体的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29061656/

相关文章:

c# - 从 3 个通用类型中推断出 2 个

c# - 如何从中继器控件检索详细信息以在模式弹出窗口中显示

c# - 使用 Asp.Net 5 Identity 3.0 注销后未删除 Cookie

c# - 从 KeyValuePairs 集合中获取 Key

Linq查询查找日期范围

entity-framework - EF代码优先循环引用

c# - 添加和更新记录的灵活方法

c# - Solace QueueNotFound 响应代码

linq - 具有隐式排序顺序的 IList

c# - EF Code First 处理多对多关系