zoukankan      html  css  js  c++  java
  • EF5.x Code First 一对多关联条件查询,Contains,Any,All

    背景

    通过多个部门id获取所有用户,部门和用户是多对多。

    已知部门id,获取该部门包括该部门下的所有子部门的所有用户。

    关系如下:

    public class Entity:IEntity
        {
            public Guid Id { get; set; }
    
            public string CreateUser { get; set; }
            public DateTime CreateTime { get; set; }
            public string ModifyUser { get; set; }
            public DateTime? ModifyTime { get; set; }
            [Timestamp]
            public Byte[] RowVersion { get; set; }
        }
    //组织架构
    public class WMS_Org : Entity
        {
            public WMS_Org() { }
    
            public string OrgName { get; set; }
            public string OrgDesc { get; set; }
            public int OrgOrder { get; set; }
            public string OrgFatherId { get; set; }
            public virtual ICollection<WMS_OrgUser> OrgUserIds { get; set; }
        }
    //用户
     public class WMS_User : Entity
        {
            public WMS_User() { }
    
            public string UserName { get; set; }
            public string NickName { get; set; }
            public string UserPwd { get; set; }
            public string Sex { get; set; }
            public string Phone { get; set; }
            public string Email { get; set; }
            public string QQ { get; set; }
            public string Address { get; set; }
            public string Remark { get; set; }
            public virtual ICollection<WMS_OrgUser> UserOrgIds { get; set; }
        }
    //组织架构和用户的关联
    public class WMS_OrgUser : Entity
        {
            public WMS_OrgUser() { }
    
            public Guid OrgId { get; set; }
            [ForeignKey("OrgId")]
            public virtual WMS_Org Org { get; set; }
    
            public Guid UserId { get; set; }
            [ForeignKey("UserId")]
            public virtual WMS_User User { get; set; }
        }
    已知组织的id

    如上图,我单击0100组织架构,要获取该组织架构下的所有用户,首先由于用户是挂载到每个节点上的,所有需要事先遍历获取所有的子节点获取节点的id

    放到Guid[]数组里

    提交后台查询
    //DBSET=DbSet<WMS_User>,ids=Guid[] ids参数
    //第一种方式All
    DBSET.Where(p => p.UserOrgIds.All(o=>ids.Contains(o.OrgId)));
    
    //第二种方式Any
    DBSET.Where(p => p.UserOrgIds.Any(o=>ids.Contains(o.OrgId)));

    注意EF采用Contains构造in的sql语句

    很直观的可以看出两个区别,一个是All,一个Any,那么产生的sql有什么区别呢?

    //All,EF产生的是inner Join
    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[UserName] AS [UserName], 
    [Extent1].[NickName] AS [NickName], 
    [Extent1].[UserPwd] AS [UserPwd], 
    [Extent1].[Sex] AS [Sex], 
    [Extent1].[Phone] AS [Phone], 
    [Extent1].[Email] AS [Email], 
    [Extent1].[QQ] AS [QQ], 
    [Extent1].[Address] AS [Address], 
    [Extent1].[Remark] AS [Remark], 
    [Extent1].[Disable] AS [Disable], 
    [Extent1].[CreateUser] AS [CreateUser], 
    [Extent1].[CreateTime] AS [CreateTime], 
    [Extent1].[ModifyUser] AS [ModifyUser], 
    [Extent1].[ModifyTime] AS [ModifyTime], 
    [Extent1].[RowVersion] AS [RowVersion]
    FROM [dbo].[WMS_User] AS [Extent1]
    WHERE NOT EXISTS (
    SELECT 1 AS [C1]
    FROM [dbo].[WMS_OrgUser] AS [Extent2]
    WHERE ([Extent1].[Id] = [Extent2].[UserId])
    AND (
    (
    NOT (
    [Extent2].[OrgId] IN (CAST('4e108b91-be3c-4cf4-a074-3767b9b8c7dc' AS UNIQUEIDENTIFIER), 
    CAST('1cc15f8c-3758-47d3-862a-5287ab5d0651' AS UNIQUEIDENTIFIER), 
    CAST('e1bf6f5a-800a-4fd4-9309-576c1d84ba2f' AS UNIQUEIDENTIFIER), 
    CAST('a436b8a9-4b3a-4bf9-bbdd-839571e03915' AS UNIQUEIDENTIFIER), 
    CAST('b0d6aead-e72f-4fd5-b2cd-e575454d3a4c' AS UNIQUEIDENTIFIER))
    )
    )
    OR (
    CASE 
    WHEN (
    [Extent2].[OrgId] IN (
    CAST('4e108b91-be3c-4cf4-a074-3767b9b8c7dc' AS UNIQUEIDENTIFIER), 
    CAST('1cc15f8c-3758-47d3-862a-5287ab5d0651' AS UNIQUEIDENTIFIER), 
    CAST('e1bf6f5a-800a-4fd4-9309-576c1d84ba2f' AS UNIQUEIDENTIFIER), 
    CAST('a436b8a9-4b3a-4bf9-bbdd-839571e03915' AS UNIQUEIDENTIFIER), 
    CAST('b0d6aead-e72f-4fd5-b2cd-e575454d3a4c' AS UNIQUEIDENTIFIER))
    ) THEN CAST(1 AS BIT)
    WHEN (
    NOT (
    [Extent2].[OrgId] IN (
    CAST('4e108b91-be3c-4cf4-a074-3767b9b8c7dc' AS UNIQUEIDENTIFIER), 
    CAST('1cc15f8c-3758-47d3-862a-5287ab5d0651' AS UNIQUEIDENTIFIER), 
    CAST('e1bf6f5a-800a-4fd4-9309-576c1d84ba2f' AS UNIQUEIDENTIFIER), 
    CAST('a436b8a9-4b3a-4bf9-bbdd-839571e03915' AS UNIQUEIDENTIFIER), 
    CAST('b0d6aead-e72f-4fd5-b2cd-e575454d3a4c' AS UNIQUEIDENTIFIER))
    )
    ) THEN CAST(0 AS BIT)
    END IS NULL
    )
    )
    )
    //Any方式,EF生成的Exists
    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[UserName] AS [UserName], 
    [Extent1].[NickName] AS [NickName], 
    [Extent1].[UserPwd] AS [UserPwd], 
    [Extent1].[Sex] AS [Sex], 
    [Extent1].[Phone] AS [Phone], 
    [Extent1].[Email] AS [Email], 
    [Extent1].[QQ] AS [QQ], 
    [Extent1].[Address] AS [Address], 
    [Extent1].[Remark] AS [Remark], 
    [Extent1].[CreateUser] AS [CreateUser], 
    [Extent1].[CreateTime] AS [CreateTime], 
    [Extent1].[ModifyUser] AS [ModifyUser], 
    [Extent1].[ModifyTime] AS [ModifyTime], 
    [Extent1].[RowVersion] AS [RowVersion]
    FROM [dbo].[WMS_User] AS [Extent1]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[WMS_OrgUser] AS [Extent2]
        WHERE ([Extent1].[Id] = [Extent2].[UserId]) 
        AND ([Extent2].[OrgId] IN 
        (cast('bd3c010c-476f-45e6-8d83-ad741cc55309' as uniqueidentifier),
        cast('4e108b91-be3c-4cf4-a074-3767b9b8c7dc' as uniqueidentifier),
        cast('1cc15f8c-3758-47d3-862a-5287ab5d0651' as uniqueidentifier),
        cast('e1bf6f5a-800a-4fd4-9309-576c1d84ba2f' as uniqueidentifier),
        cast('a436b8a9-4b3a-4bf9-bbdd-839571e03915' as uniqueidentifier),
        cast('b0d6aead-e72f-4fd5-b2cd-e575454d3a4c' as uniqueidentifier),
        cast('79ddb55a-1587-4928-a312-58da0c091459' as uniqueidentifier),
        cast('618de87e-2d97-4c0a-b6c1-acd072c305e2' as uniqueidentifier)))
    )

    也就是说All是包括条件和不在条件之内的任何值,而Any是严格在条件之内的值,但其实我们想要的是Inner Join的方式,相当于是懒加载方式,那么需要加上Include,也就是

    IQueryable<WMS_OrgUser> test5 = _db.wmsOrgUser.Include("User").Where(p => ids.Contains(p.OrgId));
    SELECT 
    1 AS [C1], 
    [Extent1].[Id] AS [Id], 
    [Extent1].[OrgId] AS [OrgId], 
    [Extent1].[UserId] AS [UserId], 
    [Extent1].[CreateUser] AS [CreateUser], 
    [Extent1].[CreateTime] AS [CreateTime], 
    [Extent1].[ModifyUser] AS [ModifyUser], 
    [Extent1].[ModifyTime] AS [ModifyTime], 
    [Extent1].[RowVersion] AS [RowVersion], 
    [Extent2].[Id] AS [Id1], 
    [Extent2].[UserName] AS [UserName], 
    [Extent2].[NickName] AS [NickName], 
    [Extent2].[UserPwd] AS [UserPwd], 
    [Extent2].[Sex] AS [Sex], 
    [Extent2].[Phone] AS [Phone], 
    [Extent2].[Email] AS [Email], 
    [Extent2].[QQ] AS [QQ], 
    [Extent2].[Address] AS [Address], 
    [Extent2].[Remark] AS [Remark], 
    [Extent2].[Disable] AS [Disable], 
    [Extent2].[CreateUser] AS [CreateUser1], 
    [Extent2].[CreateTime] AS [CreateTime1], 
    [Extent2].[ModifyUser] AS [ModifyUser1], 
    [Extent2].[ModifyTime] AS [ModifyTime1], 
    [Extent2].[RowVersion] AS [RowVersion1]
    FROM  [dbo].[WMS_OrgUser] AS [Extent1]
    INNER JOIN [dbo].[WMS_User] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id]
    WHERE [Extent1].[OrgId] IN (
    	cast('4e108b91-be3c-4cf4-a074-3767b9b8c7dc' as uniqueidentifier),
    	cast('1cc15f8c-3758-47d3-862a-5287ab5d0651' as uniqueidentifier),
    	cast('e1bf6f5a-800a-4fd4-9309-576c1d84ba2f' as uniqueidentifier),
    	cast('a436b8a9-4b3a-4bf9-bbdd-839571e03915' as uniqueidentifier),
    	cast('b0d6aead-e72f-4fd5-b2cd-e575454d3a4c' as uniqueidentifier)
    )
    

      

    条件关联查询,并实现分页
    var list = dal.FindByPage(start, pageSize, u => u.OrderByDescending(c => c.CreateTime), u => u.UserOrgIds.All(o => ids.Contains(o.OrgId)), out total);
                //防止转json时候嵌套异常
                var result = from f in list
                           select new
                           {
                               Id = f.Id,
                               UserName = f.UserName,
                               Address = f.Address,
                               Email = f.Email,
                               Sex = f.Sex,
                               CreateUser = f.CreateUser,
                               CreateTime = f.CreateTime,
                               NickName = f.NickName,
                               Phone = f.Phone,
                               QQ = f.QQ,
                               Remark = f.Remark,
                               UserPwd = f.UserPwd
                           };
                return result;
     public virtual IEnumerable<T> FindByPage(int startIndex, int pageSize, Func<IQueryable<T>, IOrderedQueryable<T>> order, Expression<Func<T, bool>> filters, out int Total)
            {
                try
                {
                    IQueryable<T> rs = order(DBSET.Where(filters));
                    Total = rs.Count();
                    if (startIndex < 0 || pageSize < 1)
                    {
                        return null;// rs.ToList();
                    }
                    else
                    {
                        return rs.Skip(startIndex * pageSize).Take(pageSize).ToList();
                    }
                }
                catch (Exception e)
                {
                    Total = 0;
                    log.Error("FindByPage:" + order.ToString() + " " + filters.ToString() + " " + e.Message);
                    return null;
                }
            }

     

  • 相关阅读:
    欧拉回路和欧拉路径
    nth_element函数
    Java读写Excel
    如何指定tomcat中session过期时间
    Java 正则表达式
    Java与模式阅读笔记(1)依赖倒转原则
    Linux vi 命令详解
    native2ascii & ascii2native
    Linux 下zip包的压缩与解压
    linux设置邮件自动转发
  • 原文地址:https://www.cnblogs.com/qidian10/p/3143822.html
Copyright © 2011-2022 走看看