zoukankan      html  css  js  c++  java
  • 实战 EF(LINQ) 如何以子查询的形式来 Join

    如题,大多数网上关于 LINQ Join 的示例都是以 from x in TableA  join ... 这样的形式,这种有好处,也有劣势,就是在比如我们使用的框架如果已经封装了很多方法,比如分页方法。而我们的业务方法只需要在 Service 层调用框架的分页方法,同时注入条件拼接的委托就可以了。而这时候,为了简单,就会以调用 Join() 方法来实现关联查询,外部看起来好像是子查询,而实际上 Entity Framework 生成 SQL 时,还是会以 Inner join 的形式来生成 SQL 语句,但不管怎样,我们还是解决了我们的实际需求,也就可以说成功了。

    1. 数据库

    假设有 2 张表。Person 表和 City 表。Person 表的 CityID 关联 City 表的 ID。

    City 表:

    Person 表:

    2. 需求

    现在,前台界面有一个 checkbox 复选框组,列出所有的城市,然后用户可以选择一个或多个,比如“深圳”和“北京”,分页列出对应的人员。注意,前台界面只需要列出 Person 的 Id 和 Name 就可以了,不需要列出城市的名称。

    3. 代码

    PersonQueryCondition.cs

        public class PersonQueryCondition
        {
            public IEnumerable<string> CityNameList { get; set; }
        }

    PersonService.cs

        public class PersonService : IPersonService
        {
            private readonly IRepository<Person> _personRepository;
            private readonly IRepository<City> _cityRepository;
    
            public PersonService(IRepository<Person> personRepository,
                IRepository<City> cityRepository
                )
            {
                this._personRepository = personRepository;
                this._cityRepository = cityRepository;
            }
    
            /// <summary>
            /// 根据城市名称列表获取分页实体
            /// </summary>
            /// <param name="cityIdList"></param>
            /// <returns></returns>
            public List<Person> GetPagedList(PersonQueryCondition queryCondition, int pageIndex, int pageSize, out int recordCount)
            {
                return this._personRepository.GetListPagedByCondition<PersonQueryCondition>(c => c.Id > 0, 
                    CombineQuery, 
                    queryCondition, 
                    pageIndex, 
                    pageSize, 
                    out recordCount);
            }
    
            protected virtual IQueryable<Person> CombineQuery(IQueryable<Person> query, PersonQueryCondition queryCondition)
            {
                if (queryCondition == null)
                {
                    return query;
                }
                if (queryCondition.CityNameList != null && queryCondition.CityNameList.Any())
                {
                    query = query.Join(_cityRepository.Table, p => p.CityID, c => c.Id, (p, c) => new { Person = p, City = c })
                        .Where(a => queryCondition.CityNameList.Contains(a.City.Name))
                        .Select(c => c.Person)
                        .Distinct();
                }
                return query;
            }
        }

    请注意:如果 Person 和 City 是多对多的关系,即一个用户可以在多个城市生活,一个城市也可以有多个用户。那么如果要筛选即在 “深圳” 生活的人,又曾经在 “北京” 生活过的人,则 LINQ 的语句需要更改为:

    if (queryCondition.CityNameList != null && queryCondition.CityNameList.Any())
    {
        //这里需要循环嵌套 Join 来实现
        foreach (string cityNameItem in queryCondition.CityNameList)
        {
            query = query.Join(_cityRepository.Table, p => p.CityID, c => c.Id, (p, c) => new { Person = p, City = c })
                .Where(a => a.City.Name == cityNameItem) // 注意:这里不再是调用 .Contains 方法,而是直接等于判断。
                .Select(c => c.Person)
                .Distinct();
        }
    }
    return query;

    代码解释截图如下(注意:.Select(c => c.Person) 后必须加一个 Distinct(),因为可能包含重复元素。):

    基类方法如下:

    4. 生成 的SQL 语句

     SQL 语句如下:

    SELECT 
        [Extent1].[Id] AS [Id], 
        [Extent1].[Name] AS [Name], 
        [Extent1].[CityID] AS [CityID] 
    FROM  
        [dbo].[Person] AS [Extent1]
        INNER JOIN [dbo].[City] AS [Extent2] ON [Extent1].[CityID] = [Extent2].[Id]
    WHERE 
    (
        [Extent1].[Id] > 0
    ) 
    AND
    (
        [Extent2].[Name] IN (N'深圳', N'北京')
    ) 
    AND 
    (
        [Extent2].[Name] IS NOT NULL
    )

    谢谢浏览!

  • 相关阅读:
    DB2 for Z/os Statement prepare
    Foreign key (referential) constraints on DB2 LUW v105
    复制Informational constraints on LUW DB2 v105
    DB2 SQL Mixed data in character strings
    DB2 create partitioned table
    MVC中使用EF的技巧集(一)
    Asp.Net MVC 开发技巧(二)
    Linq使用技巧及查询示例(一)
    Asp.Net MVC 开发技巧(一)
    Asp.Net MVC Identity 2.2.1 使用技巧(八)
  • 原文地址:https://www.cnblogs.com/Music/p/linq-join-sample.html
Copyright © 2011-2022 走看看