现在开始实现ORM的主体模块,首先需要在项目中新建一个类,命名为DbAccess,然后在项目的引用中添加两个dll,分别是MySql.Data.dll和System.Data.SQLite.dll,这两个dll都可以在对应的数据库官网上下载到,为了方便我这里也提供一个下载地址。添加好dll后需要在DbAccess中添加几个名空间,具体代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
using System.Reflection;
using MySql.Data;
using MySql.Data.MySqlClient;

下面开始实现ORM,首先需要实现对数据库的访问,具体代码如下:

private DbConnection dbConnection;  

private DbCommand dbCommand;  

private DbDataReader reader;  

//打开数据库连接
public void OpenDB()
{
try
{
switch (DbConfig.Type)
{
case DbType.Sqlite: dbConnection = new SQLiteConnection("data source = " + DbConfig.Host); break;
case DbType.Mysql: dbConnection = new MySqlConnection(DbConfig.Host); break;
default: break;
}
dbConnection.Open();
}
catch (Exception e)
{
throw e;
}
} //关闭数据库连接
public void CloseSqlConnection()
{
if (dbCommand != null)
{
dbCommand.Dispose();
}
dbCommand = null;
if (reader != null)
{
reader.Dispose();
}
reader = null;
if (dbConnection != null && dbConnection.State == ConnectionState.Open)
{
dbConnection.Close();
dbConnection.Dispose();
}
dbConnection = null;
} //执行Sql命令
public int ExecuteQuery(string sql)
{
OpenDB();
dbCommand = dbConnection.CreateCommand();
dbCommand.CommandText = sql;
reader = dbCommand.ExecuteReader();
return reader.RecordsAffected;
}

实现了对数据库的连接访问后就可以开始具体实现ORM了,首先实现两个查询方法:FirstOrDefault和Fetch,分别实现查询第一个满足条件的记录和查询所有满足条件的记录,代码如下:

//查询符合条件的第一个记录
public T FirstOrDefault<T>(Sql sql)
{
try
{
ExecuteQuery(sql.GetSql());
T result = default(T);
if (reader.Read())
{
Type type = typeof(T);
if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type.IsEnum)
{
if (type.IsEnum)
{
result = (T)Enum.ToObject(type, reader.GetValue());
}
else
{
result = (T)Convert.ChangeType(reader.GetValue(), type);
}
}
else
{
result = Activator.CreateInstance<T>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string columName = AttributeProcess.GetColumnName(property);
if (property.PropertyType.IsEnum)
{
property.SetValue(result, Enum.ToObject(property.PropertyType, reader.GetValue(reader.GetOrdinal(columName))), null);
}
else
{
property.SetValue(result, Convert.ChangeType(reader.GetValue(reader.GetOrdinal(columName)), property.PropertyType), null);
}
}
}
}
return result;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //查询所有符合条件的记录
public List<T> Fetch<T>(Sql sql)
{
try
{
ExecuteQuery(sql.GetSql());
List<T> list = new List<T>();
Type type = typeof(T);
if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type.IsEnum)
{
while (reader.Read())
{
if (type.IsEnum)
{
list.Add((T)Enum.ToObject(type, reader.GetValue()));
}
else
{
list.Add((T)Convert.ChangeType(reader.GetValue(), type));
}
}
}
else
{
while (reader.Read())
{
T result = Activator.CreateInstance<T>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string columName = AttributeProcess.GetColumnName(property);
if (property.PropertyType.IsEnum)
{
property.SetValue(result, Enum.ToObject(property.PropertyType, reader.GetValue(reader.GetOrdinal(columName))), null);
}
else
{
property.SetValue(result, Convert.ChangeType(reader.GetValue(reader.GetOrdinal(columName)), property.PropertyType), null);
}
}
list.Add(result);
}
}
return list;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
}

这里有两点需要注意,第一、一定要再finally中执行CloseSqlConnection,确保每次查询结束后都会关闭连接,哪怕是查询时出现异常。第二、对于只查询一列的情况要特殊处理。
下面来实现增删改三个方法,代码如下:

/// <summary>
/// 更新指定的列
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <param name="columns"></param>
/// <returns></returns>
public bool Update<T>(T data, IEnumerable<string> columns)
{
try
{
if (columns == null || columns.Count() == )
{
Update<T>(data);
}
Type type = data.GetType();
string table = AttributeProcess.GetTableName(type);
string sql = "Update " + table + " Set ";
string where = " Where ";
List<string> sets = new List<string>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string column = AttributeProcess.GetColumnName(property);
if (!AttributeProcess.IsPrimary(type, property))
{
if (columns.Any(a => a == column))
{
if (property.PropertyType == typeof(bool))
{
bool value = bool.Parse(property.GetValue(data, null).ToString());
sets.Add(column + "=" + (value ? "" : ""));
}
else if (property.PropertyType.IsPrimitive)
{
sets.Add(column + "=" + property.GetValue(data, null));
}
else if (property.PropertyType.IsEnum)
{
int intValue = (int)property.GetValue(data, null);
sets.Add(column + "=" + intValue);
}
else
{
if (Sql.InjectionDefend(property.GetValue(data, null).ToString()))
{
sets.Add(column + "=\'" + property.GetValue(data, null) + "\'");
}
}
}
}
else
{
if (property.PropertyType.IsPrimitive)
{
where += column + "=" + property.GetValue(data, null);
}
else
{
where += column + "=\'" + property.GetValue(data, null) + "\'";
}
}
}
sql += (string.Join(",", sets) + where);
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //更新指定的记录
public bool Update<T>(T data)
{
try
{
Type type = data.GetType();
string table = AttributeProcess.GetTableName(type);
string sql = "Update " + table + " Set ";
List<string> sets = new List<string>();
string where = " Where ";
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string column = AttributeProcess.GetColumnName(property);
if (!AttributeProcess.IsPrimary(type, property))
{
if (property.PropertyType == typeof(bool))
{
bool value = bool.Parse(property.GetValue(data, null).ToString());
sets.Add(column + "=" + (value ? "" : ""));
}
else if (property.PropertyType.IsPrimitive)
{
sets.Add(column + "=" + property.GetValue(data, null));
}
else if (property.PropertyType.IsEnum)
{
int intValue = (int)property.GetValue(data, null);
sets.Add(column + "=" + intValue);
}
else
{
if (Sql.InjectionDefend(property.GetValue(data, null).ToString()))
{
sets.Add(column + "=\'" + property.GetValue(data, null) + "\'");
}
}
}
else
{
if (property.PropertyType.IsPrimitive)
{
where += column + "=" + property.GetValue(data, null);
}
else
{
where += column + "=\'" + property.GetValue(data, null) + "\'";
}
}
}
sql += (string.Join(",", sets) + where);
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //插入新数据
public bool Insert<T>(T data)
{
try
{
Type type = data.GetType();
string table = AttributeProcess.GetTableName(type);
List<string> columns = new List<string>();
List<string> values = new List<string>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
if (!(AttributeProcess.IsPrimary(type, property) && AttributeProcess.IsIncrement(type)))
{
if (property.GetValue(data, null) != null)
{
columns.Add(AttributeProcess.GetColumnName(property));
if (property.PropertyType == typeof(bool))
{
bool value = bool.Parse(property.GetValue(data, null).ToString());
values.Add((value ? "" : ""));
}
else if (property.PropertyType.IsPrimitive)
{
values.Add(property.GetValue(data, null).ToString());
}
else if (property.PropertyType.IsEnum)
{
int intValue = (int)property.GetValue(data, null);
values.Add(intValue.ToString());
}
else
{
if (Sql.InjectionDefend(property.GetValue(data, null).ToString()))
{
values.Add("\'" + property.GetValue(data, null) + "\'");
}
}
}
}
}
string sql = "INSERT INTO " + table + "(" + string.Join(",", columns) + ")" + "VALUES" + "(" + string.Join(",", values) + ")";
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //删除数据
public bool Delete<T>(object id)
{
try
{
Type type = typeof(T);
string table = AttributeProcess.GetTableName(type);
string sql = "DELETE FROM " + table + " WHERE ";
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
if (AttributeProcess.IsPrimary(type, property))
{
sql += (AttributeProcess.GetColumnName(property) + "=");
if (property.PropertyType.IsPrimitive)
{
sql += (id.ToString() + ";");
}
else
{
sql += ("\'" + id.ToString() + "\';");
}
}
}
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
}

上面我实现了两个update,因为如果只实现一个对一行数据的所有列的update的话,那么在实现一些如更是状态等只更新某几列数据的功能时数据更新会变慢。此外还有两点需要注意,第一、每个方法最后都要关闭数据库访问连接;第二update和insert中设置数据值的地方如果数据为string类型需要进行防sql注入的操作。

下面是完整代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
using System.Reflection;
using MySql.Data;
using MySql.Data.MySqlClient; namespace ORM
{
public class DbAccess
{
private DbConnection dbConnection; private DbCommand dbCommand; private DbDataReader reader; //打开数据库连接
public void OpenDB()
{
try
{
switch (DbConfig.Type)
{
case DbType.Sqlite: dbConnection = new SQLiteConnection("data source = " + DbConfig.Host); break;
case DbType.Mysql: dbConnection = new MySqlConnection(DbConfig.Host); break;
default: break;
}
dbConnection.Open();
}
catch (Exception e)
{
throw e;
}
} //关闭数据库连接
public void CloseSqlConnection()
{
if (dbCommand != null)
{
dbCommand.Dispose();
}
dbCommand = null;
if (reader != null)
{
reader.Dispose();
}
reader = null;
if (dbConnection != null && dbConnection.State == ConnectionState.Open)
{
dbConnection.Close();
dbConnection.Dispose();
}
dbConnection = null;
} //执行Sql命令
public int ExecuteQuery(string sql)
{
OpenDB();
dbCommand = dbConnection.CreateCommand();
dbCommand.CommandText = sql;
reader = dbCommand.ExecuteReader();
return reader.RecordsAffected;
} //查询符合条件的第一个记录
public T FirstOrDefault<T>(Sql sql)
{
try
{
ExecuteQuery(sql.GetSql());
T result = default(T);
if (reader.Read())
{
Type type = typeof(T);
if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type.IsEnum)
{
if (type.IsEnum)
{
result = (T)Enum.ToObject(type, reader.GetValue());
}
else
{
result = (T)Convert.ChangeType(reader.GetValue(), type);
}
}
else
{
result = Activator.CreateInstance<T>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string columName = AttributeProcess.GetColumnName(property);
if (property.PropertyType.IsEnum)
{
property.SetValue(result, Enum.ToObject(property.PropertyType, reader.GetValue(reader.GetOrdinal(columName))), null);
}
else
{
property.SetValue(result, Convert.ChangeType(reader.GetValue(reader.GetOrdinal(columName)), property.PropertyType), null);
}
}
}
}
return result;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //查询所有符合条件的记录
public List<T> Fetch<T>(Sql sql)
{
try
{
ExecuteQuery(sql.GetSql());
List<T> list = new List<T>();
Type type = typeof(T);
if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type.IsEnum)
{
while (reader.Read())
{
if (type.IsEnum)
{
list.Add((T)Enum.ToObject(type, reader.GetValue()));
}
else
{
list.Add((T)Convert.ChangeType(reader.GetValue(), type));
}
}
}
else
{
while (reader.Read())
{
T result = Activator.CreateInstance<T>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string columName = AttributeProcess.GetColumnName(property);
if (property.PropertyType.IsEnum)
{
property.SetValue(result, Enum.ToObject(property.PropertyType, reader.GetValue(reader.GetOrdinal(columName))), null);
}
else
{
property.SetValue(result, Convert.ChangeType(reader.GetValue(reader.GetOrdinal(columName)), property.PropertyType), null);
}
}
list.Add(result);
}
}
return list;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} /// <summary>
/// 更新指定的列
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <param name="columns"></param>
/// <returns></returns>
public bool Update<T>(T data, IEnumerable<string> columns)
{
try
{
if (columns == null || columns.Count() == )
{
Update<T>(data);
}
Type type = data.GetType();
string table = AttributeProcess.GetTableName(type);
string sql = "Update " + table + " Set ";
string where = " Where ";
List<string> sets = new List<string>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string column = AttributeProcess.GetColumnName(property);
if (!AttributeProcess.IsPrimary(type, property))
{
if (columns.Any(a => a == column))
{
if (property.PropertyType == typeof(bool))
{
bool value = bool.Parse(property.GetValue(data, null).ToString());
sets.Add(column + "=" + (value ? "" : ""));
}
else if (property.PropertyType.IsPrimitive)
{
sets.Add(column + "=" + property.GetValue(data, null));
}
else if (property.PropertyType.IsEnum)
{
int intValue = (int)property.GetValue(data, null);
sets.Add(column + "=" + intValue);
}
else
{
if (Sql.InjectionDefend(property.GetValue(data, null).ToString()))
{
sets.Add(column + "=\'" + property.GetValue(data, null) + "\'");
}
}
}
}
else
{
if (property.PropertyType.IsPrimitive)
{
where += column + "=" + property.GetValue(data, null);
}
else
{
where += column + "=\'" + property.GetValue(data, null) + "\'";
}
}
}
sql += (string.Join(",", sets) + where);
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //更新指定的记录
public bool Update<T>(T data)
{
try
{
Type type = data.GetType();
string table = AttributeProcess.GetTableName(type);
string sql = "Update " + table + " Set ";
List<string> sets = new List<string>();
string where = " Where ";
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
string column = AttributeProcess.GetColumnName(property);
if (!AttributeProcess.IsPrimary(type, property))
{
if (property.PropertyType == typeof(bool))
{
bool value = bool.Parse(property.GetValue(data, null).ToString());
sets.Add(column + "=" + (value ? "" : ""));
}
else if (property.PropertyType.IsPrimitive)
{
sets.Add(column + "=" + property.GetValue(data, null));
}
else if (property.PropertyType.IsEnum)
{
int intValue = (int)property.GetValue(data, null);
sets.Add(column + "=" + intValue);
}
else
{
if (Sql.InjectionDefend(property.GetValue(data, null).ToString()))
{
sets.Add(column + "=\'" + property.GetValue(data, null) + "\'");
}
}
}
else
{
if (property.PropertyType.IsPrimitive)
{
where += column + "=" + property.GetValue(data, null);
}
else
{
where += column + "=\'" + property.GetValue(data, null) + "\'";
}
}
}
sql += (string.Join(",", sets) + where);
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //插入新数据
public bool Insert<T>(T data)
{
try
{
Type type = data.GetType();
string table = AttributeProcess.GetTableName(type);
List<string> columns = new List<string>();
List<string> values = new List<string>();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
if (!(AttributeProcess.IsPrimary(type, property) && AttributeProcess.IsIncrement(type)))
{
if (property.GetValue(data, null) != null)
{
columns.Add(AttributeProcess.GetColumnName(property));
if (property.PropertyType == typeof(bool))
{
bool value = bool.Parse(property.GetValue(data, null).ToString());
values.Add((value ? "" : ""));
}
else if (property.PropertyType.IsPrimitive)
{
values.Add(property.GetValue(data, null).ToString());
}
else if (property.PropertyType.IsEnum)
{
int intValue = (int)property.GetValue(data, null);
values.Add(intValue.ToString());
}
else
{
if (Sql.InjectionDefend(property.GetValue(data, null).ToString()))
{
values.Add("\'" + property.GetValue(data, null) + "\'");
}
}
}
}
}
string sql = "INSERT INTO " + table + "(" + string.Join(",", columns) + ")" + "VALUES" + "(" + string.Join(",", values) + ")";
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
} //删除数据
public bool Delete<T>(object id)
{
try
{
Type type = typeof(T);
string table = AttributeProcess.GetTableName(type);
string sql = "DELETE FROM " + table + " WHERE ";
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
if (AttributeProcess.IsPrimary(type, property))
{
sql += (AttributeProcess.GetColumnName(property) + "=");
if (property.PropertyType.IsPrimitive)
{
sql += (id.ToString() + ";");
}
else
{
sql += ("\'" + id.ToString() + "\';");
}
}
}
ExecuteQuery(sql);
return true;
}
catch (Exception e)
{
throw e;
}
finally
{
CloseSqlConnection();
}
}
}
}

在之前建立的userinfo表中插入一条数据用于测试,如下图:


然后在main函数中添加如下代码进行测试:

static void Main(string[] args)
{
DbAccess dao = new DbAccess();
Sql sql = new Sql();
sql.Select("*").From("userinfo");
sql.Where("Id=@0", );
User user = dao.FirstOrDefault<User>(sql);
Console.WriteLine(user.UserName);
user.UserName = "tczhoulan";
Console.WriteLine(dao.Update<User>(user, new string[] { "UserName" }));
}

执行结果如下图:


再看数据库中的数据,UserName中的值已经被修改了,如下图所示:

到这里一个简单的ORM映射框架就基本完成了,当然这只是一个最简单的ORM框架,其中还有许多不完善的地方,如有需要可以自己在上面进行扩充,我也会慢慢的进行完善。

转:C#制作ORM映射学习笔记三 ORM映射实现的更多相关文章

  1. 2018/2/13 ElasticSearch学习笔记三 自动映射以及创建自动映射模版,ElasticSearch聚合查询

    终于把这些命令全敲了一遍,话说ELK技术栈L和K我今天花了一下午全部搞定,学完后还都是花式玩那种...E却学了四天(当然主要是因为之前上班一直没时间学,还有安装服务时出现的各种error真是让我扎心了 ...

  2. JSP学习笔记(三):简单的Tomcat Web服务器

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  3. 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记

    回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...

  4. JAVA WEB学习笔记(三):简单的基于Tomcat的Web页面

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  5. Java IO学习笔记三:MMAP与RandomAccessFile

    作者:Grey 原文地址:Java IO学习笔记三:MMAP与RandomAccessFile 关于RandomAccessFile 相较于前面提到的BufferedReader/Writer和Fil ...

  6. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  7. [Firefly引擎][学习笔记三][已完结]所需模块封装

    原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读:        笔记三主要就是各个模块的封装了,这里贴 ...

  8. java之jvm学习笔记三(Class文件检验器)

    java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...

  9. VSTO学习笔记(三) 开发Office 2010 64位COM加载项

    原文:VSTO学习笔记(三) 开发Office 2010 64位COM加载项 一.加载项简介 Office提供了多种用于扩展Office应用程序功能的模式,常见的有: 1.Office 自动化程序(A ...

随机推荐

  1. 通用后台管理系统源码,响应式布局,Java管理系统源码,零门槛安装部署

    本项目是一个通用响应式管理后台,导入开发环境安装就能直接运行,界面也非诚漂亮,在PC端和移动端也是自适应的.非常适合企业或者个人搭建各种商城后台,博客后台,网站管理后台等. 源码启动后的截图 需要这套 ...

  2. Python中关于集合的介绍及用法

    一.集合的含义及创建方法 集合(set)是一种无序的并且里面存放不同元素的序列. 集合可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因 ...

  3. Scrapy用pipelines把字典保存为csv格式

    import csv class MyProjectPipeline(object): # 保存为csv格式 def __init__(self): # 打开文件,指定方式为写,利用第3个参数把csv ...

  4. 免费证书Let’s Encrypt

    我们自己也可以签发 SSL 安全证书,但是我们自己签发的安全证书不会被主流的浏览器信任,所以我们需要被信任的证书授权中心( CA )签发的安全证书.而一般的 SSL 安全证书签发服务都比较贵,比如 G ...

  5. 动态规划:ZOJ1074-最大和子矩阵 DP(最长子序列的升级版)

    To the Max Time Limit:1 Second     Memory Limit:32768 KB Problem Given a two-dimensional array of po ...

  6. 2 Model层 -定义模型

    1  ORM简介 MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库 ORM是“对象-关系-映射” ...

  7. Codeforces 653G Move by Prime 组合数学

    题意: 有一个长度为\(n\)的正整数序列\(a\),有这样一种操作: 每次可以选序列中的某一个数乘上或除以某一个素数. 求对于每一个子序列使其所有元素相等的最少操作次数之和. 分析: 因为两个素数之 ...

  8. 小米r3g旧版开发版固件,安装opkg

    1.开启ssh 1.1.刷入固件 在路由器更新界面,刷入 miwifi_r3g_firmware_c2175_2.25.122.bin 固件 下载地址: http://bigota.miwifi.co ...

  9. cf984c Finite or not?

    一个十进制分数 \(p/q\) 在 \(b\) 进制下是有限小数的充要条件是 \(q\) 的所有质因子都是 \(b\) 的质因子. First, if \(p\) and \(q\) are not ...

  10. tinyipa make

    参考:http://tinycorelinux.net/ Ironic Python Agent repo还提供了一组脚本,用于在imagebuild / tinyipa文件夹下构建一个基于Linux ...