说知识那么多不能什么都看源码和理解原理吧

   年少时,为啥不为本人的希望去努力一遍啊?纵使风声鹤唳,也不悔有这年少轻狂。感叹比很多,这段时间专业也超多,博客也少之又少更新了,究竟各个人都急需为温馨的生活去努力。

   近些日子在二个群里遇到一个人说的话,在此边不再赘言,大致意思正是和睦各个精晓种种懂,面试时各个装B种种吊,本人诚信的求教了豆蔻年华晃他,问她是或不是懂那个事物的尾巴部分原理,是还是不是理解过底层源码,能不能依据实际情形改过源码,哪个人知被她嘲讽说装X,说知识那么多不可能怎么着都看源码和透亮原理吧。然而本身只想说,那可是您协和说自身通晓,难道精晓的框架不应当掌握源码和规律吗?难道领会就是只知道怎么总结的施用吗?难道是本身拉家常的措施不对?

   近期越过三个难题,那就是有关Dapper.NET的片段主题材料,Dapper.NET的频率为什么非常高?该器件的运营原理是何等?说句实话,作者找了十分久都不曾发觉相通的篇章,不理解是否本人的搜素方式不对,还希望开掘临近好的稿子的心上人发给本身看看,知识在于分享嘛,不要吝啬你的学识,让大家一块发展呢。

   在那地差十分少介绍一下其规律  

一.Dapper.NET概述:

  项目开销时,大家都以必要酌量项指标手艺布局,尤其是对数据库底层的假造相当多。现在对此数据库的拜会有ADO.NET,EF,Dapper.NET等等,分歧的场地会有例外的挑肥拣瘦,钻探的时候都会聊到“xx很牛逼,xx效用相当的高”等等,总的来讲供给干一场,才算大家开过会。(非常多时候,在开会前项目选什么工夫已经定了,可是不开个会就呈现做事不严峻...),在采纳Dapper.NET时,有些人提起Dapper.NET效能高,很牛逼,也不亮堂极其新人说了一句“为啥Dapper.NET效率高?”

   好尴尬...

   Dapper.NET是三个简约的ORM,特意从SQL查询结果中飞快变动对象。Dapper.Net帮助实践sql查询并将其结果映射到强类型列表或动态目的列表。Dapper.Net缓存各种查询的新闻。这种周全的缓存有扶助从大意上两倍于LINQ到SQL的查询生成对象。当前缓存由五个ConcurrentDictionary对象管理,它们未有被消释。

   Dapper.Net通过扩展方法将五个映射函数增加到IDbConnection接口,那个函数都命名叫ExecuteMapperQuery。第多个映射结果是二个强类型列表,而首个映射结果是三个动态目的列表。ExecuteMapperCommand进行何况不回来结果集。全数四个主意都将参数接收为无名类,当中属性值映射到同名的SQL参数。

   Dapper.Net目的在于仅管理结果集到对象映射。它不管理指标之间的关系,它不会自动生成其余项目标SQL查询。

二.Dapper.NET原理深入分析:

   通过Dapper.NET的源码大家能够开采其首如若“分局方法和总局类”,有关于“分公司方法和根据地类”的文化能够看那篇博客:。Dapper.Net也如果连接已展开并筹划妥帖,Dapper.NET通过对IDbConnection接口进行扩展。在Dapper.NET对数据库连接成功后,能够扩充相关的操作,接下去大家就来看一下这个操作的得以达成方式。

   1.Query()方法:

Query<T>(this IDbConnection cnn, string sql, object param = null, 
         IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null

   改方法表示施行查询,重返按T输入的数量。该措施是Query(卡塔尔(قطر‎方法的泛型方法,有7个参数,第四个参数为IDbConnection扩张类,表示对IDbConnection接口举办增加,该方式应用了可选参数,进步措施的扩大性。在Query方法的兑现中,有二个CommandDefinition类,用来代表sql操作的显要方面。在这里类下有二个GetInit(卡塔尔(قطر‎方法。

   2.GetInit()方法:

    大家都驾驭Dapper.NET通过Emit反射IDataReader的队列队列,来一点也不慢的获取和产生对象。GetInit(卡塔尔(英语:State of Qatar)方法是贰个静态方法,该办法的“Type commandType”参数表示连接关联的Command对象,再次来到三个Action<IDbCommand>委托。

   大家就实际看一下是什么样通过Emit反射IDataReader的队列队列的。

if (SqlMapper.Link<Type, Action<IDbCommand>>.TryGet(commandInitCache, commandType, out action)){ return action; }

   Link<TKey, TValue>是三个泛型事务厅类,那是二个微缓存,查看是或不是存在二个Action<IDbCommand>的嘱托。

var bindByName = GetBasicPropertySetter(commandType, "BindByName", typeof(bool));
var initialLongFetchSize = GetBasicPropertySetter(commandType, "InitialLONGFetchSize", typeof(int));

   以上多个操作首要得到BindByName和InitialLONGFetchSize的收获基个性能设置。

    if (bindByName != null || initialLongFetchSize != null)
            {
                var method = new DynamicMethod(commandType.Name   "_init", null, new Type[] { typeof(IDbCommand) });
                var il = method.GetILGenerator();
                if (bindByName != null)
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Castclass, commandType);
                    il.Emit(OpCodes.Ldc_I4_1);
                    il.EmitCall(OpCodes.Callvirt, bindByName, null);
                }
                if (initialLongFetchSize != null)
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Castclass, commandType);
                    il.Emit(OpCodes.Ldc_I4_M1);
                    il.EmitCall(OpCodes.Callvirt, initialLongFetchSize, null);
                }
                il.Emit(OpCodes.Ret);
                action = (Action<IDbCommand>)method.CreateDelegate(typeof(Action<IDbCommand>));
            }

   这一步是该操作的为主部分,利用Emit反射操作。遵照上一步获取的相应名称的基特性子设置,选拔DynamicMethod对象,定义和代表二个得以编写翻译,试行和丢弃的动态方法。摈弃的章程可用于垃圾回笼。调用该对象的GetILGenerator方法,重返方法的Microsoft中间语言(MSIL)生成器,暗许的MSIL流大小为64字节。剖断基天品质设置不为空后,调用ILGenerator类的Emit方法,Emit(卡塔尔国将钦赐的授命放在指令流上,该措施选择三个IL流。EmitCall(卡塔尔将 call 或 callvirt 指令置于 Microsoft 中间语言 (MSIL卡塔尔国流,以调用varargs 方法。大家看出OpCodes类,该类描述中间语言 (IL卡塔尔指令。CreateDelegate(卡塔尔(英语:State of Qatar)完结动态方法并创立叁个可用以施行它的委托。

   通过以上的反光操作塑造好对象后,就能够随着实施相应的数据库操作。

 3.QueryImpl():

 private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefinition command, Type effectiveType)
        {
            object param = command.Parameters;
            var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param == null ? null : param.GetType(), null);
            var info = GetCacheInfo(identity, param, command.AddToCache);
            IDbCommand cmd = null;
            IDataReader reader = null;
            bool wasClosed = cnn.State == ConnectionState.Closed;
            try
            {
                cmd = command.SetupCommand(cnn, info.ParamReader);
                if (wasClosed) cnn.Open();
                reader = cmd.ExecuteReader(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess);
                wasClosed = false; 
                var tuple = info.Deserializer;
                int hash = GetColumnHash(reader);
                if (tuple.Func == null || tuple.Hash != hash)
                {
                    if (reader.FieldCount == 0) 
                        yield break;
                    tuple = info.Deserializer = new DeserializerState(hash, GetDeserializer(effectiveType, reader, 0, -1, false));
                    if (command.AddToCache) SetQueryCache(identity, info);
                }
                var func = tuple.Func;
                var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
                while (reader.Read())
                {
                    object val = func(reader);
                    if (val == null || val is T)
                    {
                        yield return (T)val;
                    }
                    else
                    {
                        yield return (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
                    }
                }
                while (reader.NextResult()) { }
                reader.Dispose();
                reader = null;
                command.OnCompleted();
            }
            finally
            {
                if (reader != null)
                {
                    if (!reader.IsClosed) try { cmd.Cancel(); }
                        catch { /* don't spoil the existing exception */ }
                    reader.Dispose();
                }
                if (wasClosed) cnn.Close();
                if (cmd != null) cmd.Dispose();
            }
        }

    该方式为进行查询操作的骨干措施,通过CommandDefinition类的相干操作后,获取到相应的指标后,实践这一步操作。该措施是IDbConnection的恢宏方法,CommandDefinition表示sql的有关操作对象,Type表示传入的八个可行的门类。Identity对象表示Dapper中的缓存查询的标记,该类是三个分公司类,能够对其進展对应的恢宏。GetCacheInfo(卡塔尔(قطر‎获取缓存音讯。

三.Dapper.NET扩展:

   那生机勃勃有些是顺水人情,该有的代码是对Dapper.NET代码做生龙活虎封装,能够附近于操作其余ORM的章程,供给者能够自取,就绝不四处去找那一个事物了。

   Dapper.NET扩张方法包

    Dapper包

四.总结:

    那篇博文是本人硬着头皮写的,因为基本未有接近的稿子,连参照他事他说加以考查的资料都还没,最多的正是调用代码的demo,对于原理和底部源码深入分析基本未有,在此边就用那篇博文引出大神对其无所不至的解析。希望对大家有好几帮扶,也好不轻易尽力了。

本文由澳门皇冠844网站发布于健康生活,转载请注明出处:说知识那么多不能什么都看源码和理解原理吧

您可能还会对下面的文章感兴趣: