首页 > 其他分享 >EF架构~对不起Include,是我冤枉你了!

EF架构~对不起Include,是我冤枉你了!

时间:2024-08-27 17:04:27浏览次数:11  
标签:__ 架构 EF linq ManageUserID Join1 Include Project1

EF架构~对不起Include,是我冤枉你了!

 

回到目录

之前一起认为EF的延时加载存在性能问题,主要体现在一对多关系上,它会增加与数据库的通讯,而EF本身也提供了“立即加载”include,今天主要说一下它,经过实验,证明如下:

最初接触EF延时加载时,以为只存在这种性能低下的方案,在了解include方法后,才知道这种神奇的方案,它与linq to sql中的DataLoadOptions比较类似,译为立即加载关联对象。

在这里,我对include说一声,对不起,是我冤枉你了,呵呵。

实验代码如下:

Infrastructure层:

     public IQueryable<WebManageUsers> GetWebManageUsers(ISpecification<WebManageUsers> specification)
        {
            return base.GetEntities(specification);
        }

Domain层:

复制代码
     public List<WebManageUsers> GetWebManageUsers(DateTime? from, DateTime? to, int? status)
        {
            //Create specification
            UserListSpecification dateSpecification = new UserListSpecification(from, to, status);
            var linq = _webManageUsers.GetWebManageUsers(dateSpecification)
                                     .Include(i => i.WebManageRoles)
                                     .Select(i => new WebManageUsers_Ext
                                     {
                                         CreateDate = i.CreateDate,
                                         ManageUserID = i.ManageUserID,
                                         RealName = i.RealName,
                                         WebManageRoles = i.WebManageRoles,
                                     });

             return linq.ToList<WebManageUsers>();
        }
复制代码

而前台显示就很简单了,代码省略。

产生的SQL代码:

复制代码
exec sp_executesql N'SELECT 
[Project1].[ManageUserID] AS [ManageUserID], 
[Project1].[CreateDate] AS [CreateDate], 
[Project1].[RealName] AS [RealName], 
[Project1].[C1] AS [C1], 
[Project1].[ManageRoleID] AS [ManageRoleID], 
[Project1].[RoleName] AS [RoleName], 
[Project1].[DepartmentID] AS [DepartmentID], 
[Project1].[About] AS [About], 
[Project1].[UpdateDate] AS [UpdateDate], 
[Project1].[SortNumber] AS [SortNumber], 
[Project1].[Operator] AS [Operator], 
[Project1].[Status] AS [Status], 
[Project1].[OperatorAuthority] AS [OperatorAuthority]
FROM ( SELECT 
    [Extent1].[ManageUserID] AS [ManageUserID], 
    [Extent1].[RealName] AS [RealName], 
    [Extent1].[CreateDate] AS [CreateDate], 
    [Join1].[ManageRoleID1] AS [ManageRoleID], 
    [Join1].[RoleName] AS [RoleName], 
    [Join1].[DepartmentID] AS [DepartmentID], 
    [Join1].[About] AS [About], 
    [Join1].[UpdateDate] AS [UpdateDate], 
    [Join1].[SortNumber] AS [SortNumber], 
    [Join1].[Operator] AS [Operator], 
    [Join1].[Status] AS [Status], 
    [Join1].[OperatorAuthority] AS [OperatorAuthority], 
    CASE WHEN ([Join1].[ManageUserID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM  [dbo].[WebManageUsers] AS [Extent1]
    LEFT OUTER JOIN  (SELECT [Extent2].[ManageUserID] AS [ManageUserID], [Extent3].[ManageRoleID] AS [ManageRoleID1], [Extent3].[RoleName] AS [RoleName], [Extent3].[DepartmentID] AS [DepartmentID], [Extent3].[About] AS [About], [Extent3].[UpdateDate] AS [UpdateDate], [Extent3].[SortNumber] AS [SortNumber], [Extent3].[Operator] AS [Operator], [Extent3].[Status] AS [Status], [Extent3].[OperatorAuthority] AS [OperatorAuthority]
        FROM  [dbo].[WebManageUser_WebManageRoles] AS [Extent2]
        INNER JOIN [dbo].[WebManageRoles] AS [Extent3] ON [Extent3].[ManageRoleID] = [Extent2].[ManageRoleID] ) AS [Join1] ON [Extent1].[ManageUserID] = [Join1].[ManageUserID]
    WHERE (@p__linq__0 = 1) AND ([Extent1].[CreateDate] > (CASE WHEN (@p__linq__1 IS NULL) THEN @p__linq__2 ELSE @p__linq__1 END)) AND ([Extent1].[CreateDate] < (CASE WHEN (@p__linq__3 IS NULL) THEN @p__linq__4 ELSE @p__linq__3 END))
)  AS [Project1]
ORDER BY [Project1].[ManageUserID] ASC, [Project1].[C1] ASC',N'@p__linq__0 bit,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7),@p__linq__3 datetime2(7),@p__linq__4 datetime2(7)',@p__linq__0=1,@p__linq__1=NULL,@p__linq__2='0001-01-01 00:00:00',@p__linq__3=NULL,@p__linq__4='9999-12-31 23:59:59.9999999'
复制代码

从上面代码上分析,主表的字段已经被过滤,include里的表字段无法过滤,这是正常的,呵呵!

最后贡献一下ObjectContext和DbContext环境下,对Include方法的扩展,使它支持lambda表达式。

复制代码
namespace Domain.Core.Extensions
{

    /// <summary>
    /// Class for IQuerable extensions methods
    /// <remarks>
    /// Include method in IQueryable ( base contract for IObjectSet ) is 
    /// intended for mock Include method in ObjectQuery{T}.
    /// Paginate solve not parametrized queries issues with skip and take L2E methods
    /// </remarks>
    /// </summary>
    public static class IQueryableExtensions
    {

        #region Extension Methods

        /// <summary>
        /// Include method for IQueryable
        /// </summary>
        /// <typeparam name="TEntity">Type of elements</typeparam>
        /// <param name="queryable">Queryable object</param>
        /// <param name="path">Path to include</param>
        /// <returns>Queryable object with include path information</returns>
        public static IQueryable<TEntity> Include<TEntity>(this IQueryable<TEntity> queryable, string path)
            where TEntity : class
        {
            if (String.IsNullOrEmpty(path))
                throw new ArgumentNullException("path can not empty");
            //  var query = queryable as ObjectQuery<TEntity>;//ObjectContext時用
            var query = queryable as DbQuery<TEntity>;//DbContext時用

            if (query != null)//if is a EF ObjectQuery object
                return query.Include(path);
            return null;
        }

        /// <summary>
        /// Include extension method for IQueryable
        /// </summary>
        /// <typeparam name="TEntity">Type of elements in IQueryable</typeparam>
        /// <param name="queryable">Queryable object</param>
        /// <param name="path">Expression with path to include</param>
        /// <returns>Queryable object with include path information</returns>
        public static IQueryable<TEntity> Include<TEntity>(this IQueryable<TEntity> queryable, Expression<Func<TEntity, object>> path)
            where TEntity : class
        {
            return Include<TEntity>(queryable, AnalyzeExpressionPath(path));
        }

        /// <summary>
        /// Paginate query in a specific page range
        /// </summary>
        /// <typeparam name="TEntity">Typeof entity in underlying query</typeparam>
        /// <typeparam name="S">Typeof ordered data value</typeparam>
        /// <param name="queryable">Query to paginate</param>
        /// <param name="orderBy">Order by expression used in paginate method
        /// <remarks>
        /// At this moment Order by expression only support simple order by c=>c.CustomerCode. If you need
        /// add more complex order functionality don't use this extension method
        /// </remarks>
        /// </param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageCount">Page count</param>
        /// <param name="ascending">order direction</param>
        /// <returns>A paged queryable</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static IQueryable<TEntity> Paginate<TEntity, S>(this IQueryable<TEntity> queryable, Expression<Func<TEntity, S>> orderBy, int pageIndex, int pageCount, bool ascending)
            where TEntity : class
        {
            ObjectQuery<TEntity> query = queryable as ObjectQuery<TEntity>;

            if (query != null)
            {
                //this paginate method use ESQL for solve problems with Parametrized queries
                //in L2E and Skip/Take methods

                string orderPath = AnalyzeExpressionPath<TEntity, S>(orderBy);

                return query.Skip(string.Format(CultureInfo.InvariantCulture, "it.{0} {1}", orderPath, (ascending) ? "asc" : "desc"), "@skip", new ObjectParameter("skip", (pageIndex) * pageCount))
                            .Top("@limit", new ObjectParameter("limit", pageCount));

            }
            else // for In-Memory object set
                return queryable.OrderBy(orderBy).Skip((pageIndex * pageCount)).Take(pageCount);
        }

        #endregion

        #region Private Methods

        static string AnalyzeExpressionPath<TEntity, S>(Expression<Func<TEntity, S>> expression)
            where TEntity : class
        {
            if (expression == (Expression<Func<TEntity, S>>)null)
                throw new ArgumentNullException("Argument error");

            MemberExpression body = expression.Body as MemberExpression;
            if (
                    (
                    (body == null)
                    ||
                    !body.Member.DeclaringType.IsAssignableFrom(typeof(TEntity))
                    )
                    ||
                    (body.Expression.NodeType != ExpressionType.Parameter))
            {
                throw new ArgumentException("Argument error");
            }
            else
                return body.Member.Name;
        }
        #endregion
    }
}
复制代码

非常感谢您的阅读!

有时,一些知识需要我们自己去研究,探索,当你把一些鲜为人知的东西研究出来后,那种喜悦是发自内心的!

 回到目录

 

作者:仓储大叔,张占岭,
荣誉:微软MVP
QQ:853066980

支付宝扫一扫,为大叔打赏!

  分类: 其它 / Entity Framework

标签:__,架构,EF,linq,ManageUserID,Join1,Include,Project1
From: https://www.cnblogs.com/sexintercourse/p/18383142

相关文章

  • Codeforces Round 962 (Div. 3)
    A.Legs若只判断题,根据模4意义下分类即可。B.Scale模拟题,缩小同值矩阵即可。C.Sort对每个字母求前缀数量和,答案就是两端点的差。constintN=2e5+5;intT,n,q;chara[N],b[N];intc[N][26],d[N][26];signedmain(void){ for(read(T);T;T--){ read(......
  • 【大模型理论篇】通用大模型架构分类及技术统一化
    1.背景           国内的“百模大战”以及开源大模型的各类评测榜单令人眼花缭乱,极易让人陷入迷茫。面对如此众多的大模型,我们该如何审视和选择呢?本文将从大模型架构的角度,对常见的开源大模型架构进行汇总与分析。资料来源于公开的学术论文、技术报告、企业官......
  • makefile文件案例
    #////////////////////////////////Makefile五大特性:显式规则、隐晦规则、变量定义$、文件指示和注释(#)#Tab键开始#//////////////////////////////////#标准写法objects=main.oled.ouart.o/ gpio.ospi.oedit:$(objects) gcc-oedit$(objects)main.o:main.cinclude......
  • 一起搭WPF架构之界面绑定显示
    一起搭WPF架构之界面绑定显示1前言2定义文件3定义属性4控制器使用5界面内容绑定6界面效果总结1前言之前的许多介绍,已经完成界面搭建的熟悉内容,现在在搭建的基础上完成简单的界面切换。2定义文件我们在已有项目中需要定义两个CS文件,在这个两个CS文件中,我......
  • makefile基础知识
    makefile知识 1、 Makefile五大内容(显示规则、隐晦规则、变量定义、文件指示、注释)1.1、显示规则:如何生成一个或多个目标文件(要生成的文件,文件依赖的文件,生成命令);stm32:main.ohello.ogcc-ostm32main.ohello.o1.2、隐晦规则:Makefile的自动推导功能,所以隐晦规则可......
  • GaLore Memory-Efficient LLM Training by Gradient Low-Rank Projection
    目录概符号说明GaLoreZhaoJ.,ZhangZ.,ChenB.,WangZ.,AnandkumarA.andTianY.GaLore:Memory-efficientllmtrainingbygradientlow-rankprojection.ICML,2024.概本文提出了一种优化器中高效的缓存策略.符号说明\(W_t\in\mathbb{R}^{m\timesn}\),参......
  • 【项目实践】CompletableFuture异步编排在多任务并行执行中的使用
    【项目实践】CompletableFuture异步编排在多任务并行执行中的使用一、单次请求处理多任务的场景        在实际项目中,我们经常会遇到一些比较复杂的查询,需要给前端响应一个内容量较大的响应结果。例如在租房系统的app中,点击具体的某个房间查看详情,需要后端将这个房间的......
  • Apache SeaTunnel技术架构演进及其在AI领域的应用
    随着数据集成需求的增长,ApacheSeaTunnel作为新一代的数据同步引擎,不仅在技术架构上不断演进,也在AI领域展现出其独特的应用价值。在CommunityOverCodeAsia2024大会上,ApacheSeaTunnelPMCChair高俊深入探讨SeaTunnel的技术演进路径,分析其在AI领域的应用案例,并展望未来的发展......
  • JuiceFS元数据引擎PostgreSQL
    使用PostgreSQL作为JuiceFS元数据引擎,各表的含义和字段做一个简单归纳juicefs数据库用于存储juicefs文件信息postgres=#\lListofdatabasesName|Owner|Encoding|LocaleProvider|Collate|......
  • BAdam A Memory Efficient Full Parameter Optimization Method for Large Language M
    目录概BAdam代码LuoQ.,YuH.andLiX.BAdam:Amemoryefficientfullparameteroptimizationmethodforlargelanguagemodels.arXivpreprint,2024.概本文介绍了一种Blockcorrdinatedescent(BCD)的训练方式.BAdam当模型本身很大的时候,训练它会成为一......