【手撸一个ORM】第七步、SqlDataReader转实体
说明
使用Expression(表达式目录树)转Entity的文章在园子里有很多,思路也大致也一样,我在前面有篇文章对解决思路有些说明,有兴趣的小伙伴可以看下 (传送门),刚接触表达式目录树时写的,不太严谨,但思路上应该不会有误导群众的嫌疑,具体实现代码还是以本篇的为准。
关于缓存和缺陷
实体查询,如:db.Query<Student>().Include(s => s.School).ToList();这种形式,因其SQL语句由代码拼接生成,所以比较固定,因此在这里对齐进行了缓存,既将表达式目录树生成的委托保存在一个字典中,第一次生成后,后面的操作就可以直接从字典中拿来用,其效率提升还是蛮明显的。这里因为我这个方法是之前写好的,在生成缓存key的时候使用 实体名+导航属性(多个导航属性,先按名称排序,然后拼接)的方式来生成,其实更普遍的做法是使用SQL语句作为缓存的key。
按需查询(Select),在这个代码里没有进行缓存,因为之前考虑到 Select(s => new {...}) 这种生成匿名类的查询,查询的字段不固定,那肯定就无法进行缓存,但是到最后也没能实现,下面的SqlDataReaderMapper.cs中有不少无用的代码,其实就是对生成匿名类对象和dynamic对象的尝试,然而,并没有成功。那么,在现阶段,这里的Func也还是可以缓存的,因为没有了匿名类的不确定性,所以生成的SQL语句时固定的,那生成的委托自然也就可以缓存了。只是在我的代码中没有实现,请自行解决吧。
不得不说无法支持 Select(s => new {})确实是个挺遗憾的地方,如果需要按需加载,必须定义一个实体承载查询结果,如 StudentDto 之类的,增加工作量不说,灵活性也欠缺了一些。
用于保存导航属性信息的工具类
- using System;
- namespace MyOrm.Mappers
- {
- public class IncludePropertySdrMap
- {
- public Type Type { get; set; }
- public string PropertyName { get; set; }
- public int Index { get; set; }
- }
- }
用于实体查询的转换类
- using MyOrm.Reflections;
- using System;
- using System.Collections.Generic;
- using System.Data.SqlClient;
- using System.Linq;
- using System.Linq.Expressions;
- namespace MyOrm.Mappers
- {
- public class SqlDataReaderConverter<T> where T : class, new()
- {
- private static readonly Dictionary<string, Func<SqlDataReader, T>> Dict
- = new Dictionary<string, Func<SqlDataReader, T>>();
- public MyEntity Master { get; set; }
- public List<string> Includes { get; set; }
- public string Key { get; set; }
- public SqlDataReaderConverter(string[] props = null)
- {
- Master = MyEntityContainer.Get(typeof(T));
- if (props == null || props.Length == )
- {
- Includes = new List<string>();
- Key = typeof(T).Name;
- }
- else
- {
- Includes = props.ToList();
- Key = typeof(T).Name + "-" + string.Join("-", props.OrderBy(p => p).Distinct());
- }
- }
- #region 反射
- public T ConvertToEntity(SqlDataReader sdr)
- {
- var entity = new T();
- foreach (var property in Master.Properties)
- {
- property.PropertyInfo.SetValue(entity, sdr[property.Name]);
- }
- foreach (var include in Includes)
- {
- var prop = Master.Properties.Single(p => p.Name == include);
- if (prop != null)
- {
- var subType = prop.PropertyInfo.PropertyType;
- var subEntityInfo = MyEntityContainer.Get(subType);
- var subEntity = Activator.CreateInstance(subType);
- foreach (var subProperty in subEntityInfo.Properties)
- {
- if (subProperty.IsMap)
- {
- subProperty.PropertyInfo.SetValue(subEntity, sdr[$"{include}_{subProperty.Name}"]);
- }
- }
- prop.PropertyInfo.SetValue(entity, subEntity);
- }
- }
- return entity;
- }
- #endregion
- #region 表达式目录树
- public Func<SqlDataReader, T> GetFunc(SqlDataReader sdr)
- {
- if (!Dict.TryGetValue(Key, out var func))
- {
- var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
- var memberBindings = new List<MemberBinding>();
- var subMemberMaps = new Dictionary<string, List<IncludePropertySdrMap>>();
- foreach (var include in Includes)
- {
- subMemberMaps.Add(include, new List<IncludePropertySdrMap>());
- }
- for (var i = ; i < sdr.FieldCount; i++)
- {
- var fieldName = sdr.GetName(i);
- var fieldNames = fieldName.Split('_');
- if (fieldNames.Length == )
- {
- var property = Master.Properties.Single(p => p.Name == fieldName);
- if (property != null)
- {
- var methodName = GetSdrMethodName(property.PropertyInfo.PropertyType);
- var methodCall = Expression.Call(sdrParameter,
- typeof(SqlDataReader).GetMethod(methodName) ?? throw new InvalidOperationException(),
- Expression.Constant(i));
- Expression setValueExpression;
- if (property.PropertyInfo.PropertyType.IsGenericType &&
- property.PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
- {
- setValueExpression = Expression.Convert(methodCall, property.PropertyInfo.PropertyType);
- }
- else
- {
- setValueExpression = methodCall;
- }
- //memberBindings.Add(Expression.Bind(property.PropertyInfo, methodCall));
- memberBindings.Add(
- Expression.Bind(
- property.PropertyInfo,
- Expression.Condition(
- Expression.TypeIs(
- Expression.Call(
- sdrParameter,
- typeof(SqlDataReader).GetMethod("get_Item", new[] {typeof(int)}) ??
- throw new InvalidOperationException(),
- Expression.Constant(i)),
- typeof(DBNull)
- ),
- Expression.Default(property.PropertyInfo.PropertyType),
- setValueExpression
- )
- )
- );
- }
- }
- else
- {
- if (subMemberMaps.TryGetValue(fieldNames[], out var list))
- {
- list.Add(new IncludePropertySdrMap { PropertyName = fieldNames[], Index = i });
- }
- }
- }
- foreach (var include in subMemberMaps)
- {
- var prop = Master.Properties.Single(p => p.Name == include.Key);
- if (prop != null)
- {
- var subEntityInfo = MyEntityContainer.Get(prop.PropertyInfo.PropertyType);
- var subBindingList = new List<MemberBinding>();
- foreach (var subProperty in subEntityInfo.Properties)
- {
- if (subProperty.IsMap)
- {
- var mapper = include.Value.SingleOrDefault(v => v.PropertyName == subProperty.Name);
- if (mapper != null)
- {
- var methodName = GetSdrMethodName(subProperty.PropertyInfo.PropertyType);
- var methodCall = Expression.Call(
- sdrParameter,
- typeof(SqlDataReader).GetMethod(methodName) ??
- throw new InvalidOperationException(),
- Expression.Constant(mapper.Index));
- Expression setValueExpression;
- if (subProperty.PropertyInfo.PropertyType.IsGenericType &&
- subProperty.PropertyInfo.PropertyType.GetGenericTypeDefinition() ==
- typeof(Nullable<>))
- {
- setValueExpression = Expression.Convert(methodCall,
- subProperty.PropertyInfo.PropertyType);
- }
- else
- {
- setValueExpression = methodCall;
- }
- subBindingList.Add(
- Expression.Bind(
- subProperty.PropertyInfo,
- Expression.Condition(
- Expression.TypeIs(
- Expression.Call(
- sdrParameter,
- typeof(SqlDataReader).GetMethod("get_Item",
- new[] {typeof(int)}) ??
- throw new InvalidOperationException(),
- Expression.Constant(mapper.Index)),
- typeof(DBNull)
- ),
- Expression.Default(subProperty.PropertyInfo.PropertyType),
- setValueExpression
- )
- )
- );
- }
- }
- var subInitExpression = Expression.MemberInit(
- Expression.New(prop.PropertyInfo.PropertyType),
- subBindingList);
- memberBindings.Add(Expression.Bind(prop.PropertyInfo, subInitExpression));
- }
- }
- }
- var initExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindings);
- func = Expression.Lambda<Func<SqlDataReader, T>>(initExpression, sdrParameter).Compile();
- Dict.Add(Key, func);
- }
- else
- {
- //Console.WriteLine("应用了缓存");
- }
- return func;
- }
- public T ConvertToEntity2(SqlDataReader sdr)
- {
- if (sdr.HasRows)
- {
- var func = GetFunc(sdr);
- if (sdr.Read())
- {
- return func.Invoke(sdr);
- }
- }
- return default(T);
- }
- public List<T> ConvertToEntityList(SqlDataReader sdr)
- {
- var result = new List<T>();
- if (!sdr.HasRows)
- {
- return result;
- }
- var func = GetFunc(sdr);
- do
- {
- while (sdr.Read())
- {
- result.Add(func(sdr));
- }
- } while (sdr.NextResult());
- return result;
- }
- public List<T> ConvertToEntityList2(SqlDataReader sdr)
- {
- var result = new List<T>();
- while (sdr.Read())
- {
- result.Add(ConvertToEntity2(sdr));
- }
- return result;
- }
- /// <summary>
- /// 获取SqlDataReader转实体属性时调用的方法名
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- private string GetSdrMethodName(Type type)
- {
- var realType = GetRealType(type);
- string methodName;
- if (realType == typeof(string))
- {
- methodName = "GetString";
- }
- else if (realType == typeof(int))
- {
- methodName = "GetInt32";
- }
- else if (realType == typeof(DateTime))
- {
- methodName = "GetDateTime";
- }
- else if (realType == typeof(decimal))
- {
- methodName = "GetDecimal";
- }
- else if (realType == typeof(Guid))
- {
- methodName = "GetGuid";
- }
- else if (realType == typeof(bool))
- {
- methodName = "GetBoolean";
- }
- else
- {
- throw new ArgumentException($"不受支持的类型:{type.FullName}");
- }
- return methodName;
- }
- private static Type GetRealType(Type type)
- {
- var realType = type.IsGenericType &&
- type.GetGenericTypeDefinition() == typeof(Nullable<>)
- ? type.GetGenericArguments()[]
- : type;
- return realType;
- }
- #endregion
- }
- }
用于按需查询的转换类
- using System;
- using System.Collections.Generic;
- using System.Data.SqlClient;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Text;
- using MyOrm.Expressions;
- using MyOrm.Reflections;
- namespace MyOrm.Mappers
- {
- public class SqlDataReaderMapper
- {
- public Func<SqlDataReader, TTarget> ResolveClass<TTarget>(SqlDataReader sdr)
- {
- if (!sdr.HasRows) return null;
- var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
- var memberBindings = new List<MemberBinding>();
- var subMemberMaps = new Dictionary<string, List<IncludePropertySdrMap>>();
- var masterEntity = MyEntityContainer.Get(typeof(TTarget));
- for (var i = ; i < sdr.FieldCount; i++)
- {
- var fieldName = sdr.GetName(i);
- var fieldNames = fieldName.Split("__");
- if (fieldNames.Length == )
- {
- var property = masterEntity.Properties.Single(p => p.Name == fieldName);
- if (property != null)
- {
- var methodName = GetSdrMethodName(property.PropertyInfo.PropertyType);
- var methodCall = Expression.Call(sdrParameter,
- typeof(SqlDataReader).GetMethod(methodName) ?? throw new InvalidOperationException(),
- Expression.Constant(i));
- Expression setValueExpression;
- if (property.PropertyInfo.PropertyType.IsGenericType &&
- property.PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
- {
- setValueExpression = Expression.Convert(methodCall, property.PropertyInfo.PropertyType);
- }
- else
- {
- setValueExpression = methodCall;
- }
- //memberBindings.Add(Expression.Bind(property.PropertyInfo, methodCall));
- memberBindings.Add(
- Expression.Bind(
- property.PropertyInfo,
- Expression.Condition(
- Expression.TypeIs(
- Expression.Call(
- sdrParameter,
- typeof(SqlDataReader).GetMethod("get_Item", new[] { typeof(int) }) ??
- throw new InvalidOperationException(),
- Expression.Constant(i)),
- typeof(DBNull)
- ),
- Expression.Default(property.PropertyInfo.PropertyType),
- setValueExpression
- )
- )
- );
- }
- }
- else
- {
- if (subMemberMaps.TryGetValue(fieldNames[], out var list))
- {
- list.Add(new IncludePropertySdrMap { PropertyName = fieldNames[], Index = i });
- }
- }
- }
- foreach (var include in subMemberMaps)
- {
- var prop = masterEntity.Properties.Single(p => p.Name == include.Key);
- if (prop != null)
- {
- var subEntityInfo = MyEntityContainer.Get(prop.PropertyInfo.PropertyType);
- var subBindingList = new List<MemberBinding>();
- foreach (var subProperty in subEntityInfo.Properties)
- {
- if (subProperty.IsMap)
- {
- var mapper = include.Value.SingleOrDefault(v => v.PropertyName == subProperty.Name);
- if (mapper != null)
- {
- var methodName = GetSdrMethodName(subProperty.PropertyInfo.PropertyType);
- var methodCall = Expression.Call(
- sdrParameter,
- typeof(SqlDataReader).GetMethod(methodName) ??
- throw new InvalidOperationException(),
- Expression.Constant(mapper.Index));
- Expression setValueExpression;
- if (subProperty.PropertyInfo.PropertyType.IsGenericType &&
- subProperty.PropertyInfo.PropertyType.GetGenericTypeDefinition() ==
- typeof(Nullable<>))
- {
- setValueExpression = Expression.Convert(methodCall,
- subProperty.PropertyInfo.PropertyType);
- }
- else
- {
- setValueExpression = methodCall;
- }
- subBindingList.Add(
- Expression.Bind(
- subProperty.PropertyInfo,
- Expression.Condition(
- Expression.TypeIs(
- Expression.Call(
- sdrParameter,
- typeof(SqlDataReader).GetMethod("get_Item",
- new[] { typeof(int) }) ??
- throw new InvalidOperationException(),
- Expression.Constant(mapper.Index)),
- typeof(DBNull)
- ),
- Expression.Default(subProperty.PropertyInfo.PropertyType),
- setValueExpression
- )
- )
- );
- }
- }
- var subInitExpression = Expression.MemberInit(
- Expression.New(prop.PropertyInfo.PropertyType),
- subBindingList);
- memberBindings.Add(Expression.Bind(prop.PropertyInfo, subInitExpression));
- }
- }
- }
- var initExpression = Expression.MemberInit(Expression.New(typeof(TTarget)), memberBindings);
- return Expression.Lambda<Func<SqlDataReader, TTarget>>(initExpression, sdrParameter).Compile();
- }
- public Func<SqlDataReader, TTarget> ResolveConstant<TTarget>(SqlDataReader sdr, string fieldName = "")
- {
- var type = typeof(TTarget);
- var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
- MethodCallExpression callExpression;
- if (string.IsNullOrWhiteSpace(fieldName))
- {
- var methodName = GetSdrMethodName(type);
- callExpression = Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod(methodName),
- Expression.Constant());
- return Expression.Lambda<Func<SqlDataReader, TTarget>>(callExpression, sdrParameter).Compile();
- }
- else
- {
- callExpression = Expression.Call(sdrParameter,
- typeof(SqlDataReader).GetMethod("get_item", new[] {typeof(string)}),
- Expression.Constant(fieldName));
- var convertExpression = Expression.Convert(callExpression, type);
- return Expression.Lambda<Func<SqlDataReader, TTarget>>(convertExpression, sdrParameter).Compile();
- }
- }
- public Func<SqlDataReader, dynamic> Resolve2(SqlDataReader sdr)
- {
- var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
- var newExpression = Expression.New(typeof(System.Dynamic.ExpandoObject));
- var convertExpression = Expression.Convert(newExpression, typeof(IDictionary<string, object>));
- var memberBindings = new List<MemberBinding>();
- for(var i = ; i < sdr.FieldCount; i++)
- {
- var nameExpression = Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod("GetName"), Expression.Constant(i));
- //var itemExpression = Expression.Call(
- // sdrParameter,
- // typeof(SqlDataReader).GetMethod("get_Item",
- // new[] { typeof(int) }) ??
- // throw new InvalidOperationException(),
- // Expression.Constant(i));
- //var type = Expression.Constant(Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod("GetFieldType", new[] { typeof(int) }), Expression.Constant(i)));
- var valueExpression = Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod("GetValue", new[] { typeof(int) }), Expression.Constant(i));
- //var callExpression = Expression.Call(
- // convertExpression,
- // typeof(IDictionary<string, object>).GetMethod("Add"),
- // nameExpression, valueExpression);
- Expression.Call(newExpression,
- typeof(System.Dynamic.ExpandoObject).GetMethod("TryAdd", new[] { typeof(string), typeof(object) }),
- nameExpression,
- valueExpression);
- }
- var initExpression = Expression.MemberInit(newExpression);
- var lambda = Expression.Lambda<Func<SqlDataReader, dynamic>>(initExpression, sdrParameter);
- return lambda.Compile();
- }
- public List<T> ConvertToList<T>(SqlDataReader sdr)
- {
- var result = new List<T>();
- if (!sdr.HasRows)
- {
- return result;
- }
- var func = typeof(T).IsClass && typeof(T) != typeof(string) ? ResolveClass<T>(sdr) : ResolveConstant<T>(sdr);
- if (func == null)
- {
- return result;
- }
- while (sdr.Read())
- {
- result.Add(func.Invoke(sdr));
- }
- return result;
- }
- public T ConvertToEntity<T>(SqlDataReader sdr)
- {
- if (!sdr.HasRows)
- {
- return default(T);
- }
- var func = typeof(T).IsClass ? ResolveClass<T>(sdr) : ResolveConstant<T>(sdr);
- if (func == null)
- {
- return default(T);
- }
- if (sdr.Read())
- {
- return func.Invoke(sdr);
- }
- return default(T);
- }
- public List<dynamic> ConvertToList(SqlDataReader sdr)
- {
- var result = new List<dynamic>();
- if (!sdr.HasRows)
- {
- return result;
- }
- var func = Resolve2(sdr);
- if (func == null)
- {
- return result;
- }
- while (sdr.Read())
- {
- result.Add(func.Invoke(sdr));
- }
- return result;
- }
- public dynamic ConvertToEntity(SqlDataReader sdr)
- {
- if (!sdr.HasRows)
- {
- return null;
- }
- var func = Resolve2(sdr);
- if (func != null && sdr.Read())
- {
- return func.Invoke(sdr);
- }
- return null;
- }
- private string GetSdrMethodName(Type type)
- {
- var realType = GetRealType(type);
- string methodName;
- if (realType == typeof(string))
- {
- methodName = "GetString";
- }
- else if (realType == typeof(int))
- {
- methodName = "GetInt32";
- }
- else if (realType == typeof(DateTime))
- {
- methodName = "GetDateTime";
- }
- else if (realType == typeof(decimal))
- {
- methodName = "GetDecimal";
- }
- else if (realType == typeof(Guid))
- {
- methodName = "GetGuid";
- }
- else if (realType == typeof(bool))
- {
- methodName = "GetBoolean";
- }
- else
- {
- throw new ArgumentException($"不受支持的类型:{type.FullName}");
- }
- return methodName;
- }
- public Type ConvertSdrFieldToType(SqlDataReader sdr)
- {
- return null;
- }
- private static Type GetRealType(Type type)
- {
- var realType = type.IsGenericType &&
- type.GetGenericTypeDefinition() == typeof(Nullable<>)
- ? type.GetGenericArguments()[]
- : type;
- return realType;
- }
- }
- }
【手撸一个ORM】第七步、SqlDataReader转实体的更多相关文章
- 【手撸一个ORM】第一步、实体约定和描述
一.约定 数据实体必须实现 IEntity 接口,该接口定义了一个int类型的Id属性,既每个实体必须有一个名称为Id的自增主键. 若数据表的主键列名称不是Id,可以通过 [MyKey("主 ...
- 【手撸一个ORM】第九步、orm默认配置类 MyDbConfiguration,一次配置,简化实例化流程
这个实现比较简单,事实上可配置的项目很多,如有需要,请读者自行扩展 using System; namespace MyOrm { public class MyDbConfiguration { p ...
- 【手撸一个ORM】MyOrm的使用说明
[手撸一个ORM]第一步.约定和实体描述 [手撸一个ORM]第二步.封装实体描述和实体属性描述 [手撸一个ORM]第三步.SQL语句构造器和SqlParameter封装 [手撸一个ORM]第四步.Ex ...
- 【手撸一个ORM】第六步、对象表达式解析和Select表达式解析
说明 一个Orm自然不仅仅包含条件表达式,还会有如下的场景: OrderBy(s => s.StudentName) Select<StudentDto>(s => new S ...
- 【手撸一个ORM】第四步、Expression(表达式目录树)扩展
到这里,Orm的基架已经搭起来了,接下来就是激动人心的部分,表达式目录树转Sql语句,SqlDataReader转数据实体等等,但是在这之前,我们需要扩展下表达式目录树的方法,以方便后面的相关操作. ...
- 【手撸一个ORM】第十步、数据操作工具类 MyDb
说明 其实就是数据库操作的一些封装,很久不用SqlCommand操作数据库了,看了点园子里的文章就直接上手写了,功能上没问题,但写法上是否完美高效无法保证,建议有需要的朋友自己重写,当然如果能把最佳实 ...
- 【手撸一个ORM】第三步、SQL语句构造器和SqlParameter封装
既然是数据库工具,自然少不了增删改查的sql语句,在这里将这些常用SQL拼接操作集成到 [SqlServerBuilder.cs] 当中,方便后面调用. 近几年在项目中一直使用Dapper操作数据库, ...
- 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句
说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...
- 【手撸一个ORM】第八步、查询工具类
一.实体查询 using MyOrm.Commons; using MyOrm.DbParameters; using MyOrm.Expressions; using MyOrm.Mappers; ...
随机推荐
- 找工作--volatile
在Java编写的程序中,有时为了提高程序的运行效率,编译器会自动对其进行优化,把经常访问的变量缓存起来,程序在读取这个变量时有可能会直接从缓存(例如寄存器)中来读取这个值,而不会从内存中读取.这样做的 ...
- ssh配置免登 Ubuntu环境
配置之前,可能需要修改下每台机器的hostname,修改方法 1.直接修改hostname文件:sudo vi /etc/hostname 2.重启服务器:shutdown -r now Ubuntu ...
- RS485总线防雷保护方案
RS485作为最为最常用的电表通讯方式之一.日常生活中雷电和静电干扰已经成为485通信总线在实际工程经常遇到的问题.故如何对芯片以及总线进行有效的保护,是摆在每一个使用者面前的一个问题.在这里,我们主 ...
- C#使用Command将dataGrideView表格内数据与数据库交互
本文主要介绍通过Command类使用SQL插入指令insert与查询指令select将dataGrideView表格内添加至数据库,与从数据库读出数据存放在dataGrideView表格中. C#制作 ...
- springMVC绑定json参数之二(2.2.2)
二.springmvc 接收不同格式的json字符串 2).格式二:json字符串数组 前台: test = function () { var test = ["123",&qu ...
- cadence spb 16.5 破解过程实例和使用感受_赤松子耶_新浪博客
cadence spb 16.5 破解过程实例和使用感受_赤松子耶_新浪博客 Cadence Allegro16.5详细安装具体的步骤 1.下载SPB16.5下来后,点setup.exe,先安装第一项 ...
- 02_android下单元测试
Java的单元测试JUnit. Java程序入口是main方法.一般不在安卓程序入口 @Override protected void onCreate(Bundle savedInstanceSta ...
- [51nod1270] 数组的最大代价(简单dp)
解题关键:先由贪心的思想得出任何一个位置只能取1或者a[i],然后dp即可. #include<bits/stdc++.h> using namespace std; typedef lo ...
- centos MAC 地址与报错eth0 unknown interface no such device
eth0 unknown interface no such device 出现这个原因是由于虚拟机直接COPY过来,MAC地址发生了变化,但eth0 里仍然记录着旧的MAC地址. 解决方法: vim ...
- 2、linux-compress and uncompresse
1.单个文件 压缩 解压 gzip file1 gzip -d file1.gz或者gunzip file1.gz #file1文件即会被压缩为 file1.gz,file1原文件删除:解压后同样删 ...