C# SQLiteHelper类似SqlHelper类实现存取Sqlite数据库
这个类不是我实现的,原文在这里,我修改了原文中分析sql语句参数的方法,将方法名修改为AttachParameters,将其修饰符修改为private,并直接传递command到这个方法,直接绑定参数到comand。修改后的代码如下
{///<summary>///SQLiteHelper is a utility class similar to "SQLHelper" in MS///Data Access Application Block and follows similar pattern.///</summary>publicclassSQLiteHelper
{///<summary>///Creates a new<see cref="SQLiteHelper"/>instance. The ctor is marked private since all members are static.///</summary>privateSQLiteHelper()
{
}///<summary>///Creates the command.///</summary>///<param name="connection">Connection.</param>///<param name="commandText">Command text.</param>///<param name="commandParameters">Command parameters.</param>///<returns>SQLite Command</returns>publicstaticSQLiteCommand CreateCommand(SQLiteConnection connection,stringcommandText,paramsSQLiteParameter[] commandParameters)
{
SQLiteCommand cmd=newSQLiteCommand(commandText, connection);if(commandParameters.Length>0)
{foreach(SQLiteParameter parmincommandParameters)
cmd.Parameters.Add(parm);
}returncmd;
}///<summary>///Creates the command.///</summary>///<param name="connectionString">Connection string.</param>///<param name="commandText">Command text.</param>///<param name="commandParameters">Command parameters.</param>///<returns>SQLite Command</returns>publicstaticSQLiteCommand CreateCommand(stringconnectionString,stringcommandText,paramsSQLiteParameter[] commandParameters)
{
SQLiteConnection cn=newSQLiteConnection(connectionString);
SQLiteCommand cmd
=newSQLiteCommand(commandText, cn);if(commandParameters.Length>0){foreach(SQLiteParameter parmincommandParameters)
cmd.Parameters.Add(parm);
}returncmd;
}///<summary>///Creates the parameter.///</summary>///<param name="parameterName">Name of the parameter.</param>///<param name="parameterType">Parameter type.</param>///<param name="parameterValue">Parameter value.</param>///<returns>SQLiteParameter</returns>publicstaticSQLiteParameter CreateParameter(stringparameterName, System.Data.DbType parameterType,objectparameterValue)
{
SQLiteParameter parameter=newSQLiteParameter();
parameter.DbType=parameterType;
parameter.ParameterName=parameterName;
parameter.Value=parameterValue;returnparameter;
}///<summary>///Shortcut method to execute dataset from SQL Statement and object[] arrray of parameter values///</summary>///<param name="connectionString">SQLite Connection string</param>///<param name="commandText">SQL Statement with embedded "@param" style parameter names</param>///<param name="paramList">object[] array of parameter values</param>///<returns></returns>publicstaticDataSet ExecuteDataSet(stringconnectionString,stringcommandText,object[] paramList)
{
SQLiteConnection cn=newSQLiteConnection(connectionString);
SQLiteCommand cmd=cn.CreateCommand();
cmd.CommandText
=commandText;if(paramList!=null){
AttachParameters(cmd,commandText, paramList);
}
DataSet ds=newDataSet();if(cn.State==ConnectionState.Closed)
cn.Open();
SQLiteDataAdapter da=newSQLiteDataAdapter(cmd);
da.Fill(ds);
da.Dispose();
cmd.Dispose();
cn.Close();returnds;
}///<summary>///Shortcut method to execute dataset from SQL Statement and object[] arrray of parameter values///</summary>///<param name="cn">Connection.</param>///<param name="commandText">Command text.</param>///<param name="paramList">Param list.</param>///<returns></returns>publicstaticDataSet ExecuteDataSet(SQLiteConnection cn,stringcommandText,object[] paramList)
{
SQLiteCommand cmd
=cn.CreateCommand();cmd.CommandText
=commandText;if(paramList!=null){
AttachParameters(cmd,commandText, paramList);
}
DataSet ds=newDataSet();if(cn.State==ConnectionState.Closed)
cn.Open();
SQLiteDataAdapter da=newSQLiteDataAdapter(cmd);
da.Fill(ds);
da.Dispose();
cmd.Dispose();
cn.Close();returnds;
}///<summary>///Executes the dataset from a populated Command object.///</summary>///<param name="cmd">Fully populated SQLiteCommand</param>///<returns>DataSet</returns>publicstaticDataSet ExecuteDataset(SQLiteCommand cmd)
{if(cmd.Connection.State==ConnectionState.Closed)
cmd.Connection.Open();
DataSet ds=newDataSet();
SQLiteDataAdapter da=newSQLiteDataAdapter(cmd);
da.Fill(ds);
da.Dispose();
cmd.Connection.Close();
cmd.Dispose();returnds;
}///<summary>///Executes the dataset in a SQLite Transaction///</summary>///<param name="transaction">SQLiteTransaction. Transaction consists of Connection, Transaction,///and Command, all of which must be created prior to making this method call.</param>///<param name="commandText">Command text.</param>///<param name="commandParameters">Sqlite Command parameters.</param>///<returns>DataSet</returns>///<remarks>user must examine Transaction Object and handle transaction.connection .Close, etc.</remarks>publicstaticDataSet ExecuteDataset(SQLiteTransaction transaction,stringcommandText,paramsSQLiteParameter[] commandParameters)
{if(transaction==null)thrownewArgumentNullException("transaction");if(transaction!=null&&transaction.Connection==null)thrownewArgumentException("The transaction was rolled back or committed, please provide an open transaction.","transaction");
IDbCommand cmd=transaction.Connection.CreateCommand();
cmd.CommandText=commandText;foreach(SQLiteParameter parmincommandParameters)
{
cmd.Parameters.Add(parm);
}if(transaction.Connection.State==ConnectionState.Closed)
transaction.Connection.Open();
DataSet ds=ExecuteDataset((SQLiteCommand)cmd);returnds;
}///<summary>///Executes the dataset with Transaction and object array of parameter values.///</summary>///<param name="transaction">SQLiteTransaction. Transaction consists of Connection, Transaction,///and Command, all of which must be created prior to making this method call.</param>///<param name="commandText">Command text.</param>///<param name="commandParameters">object[] array of parameter values.</param>///<returns>DataSet</returns>///<remarks>user must examine Transaction Object and handle transaction.connection .Close, etc.</remarks>publicstaticDataSet ExecuteDataset(SQLiteTransaction transaction,stringcommandText,object[] commandParameters)
{if(transaction==null)thrownewArgumentNullException("transaction");if(transaction!=null&&transaction.Connection==null)thrownewArgumentException("The transaction was rolled back or committed, please provide an open transaction.","transaction");
IDbCommand cmd=transaction.Connection.CreateCommand();
cmd.CommandText=commandText;
AttachParameters((SQLiteCommand)cmd,cmd.CommandText, commandParameters);if(transaction.Connection.State==ConnectionState.Closed)
transaction.Connection.Open();
DataSet ds
=ExecuteDataset((SQLiteCommand)cmd);returnds;}#regionUpdateDataset///<summary>///Executes the respective command for each inserted, updated, or deleted row in the DataSet.///</summary>///<remarks>///e.g.:///UpdateDataset(conn, insertCommand, deleteCommand, updateCommand, dataSet, "Order");///</remarks>///<param name="insertCommand">A valid SQL statement to insert new records into the data source</param>///<param name="deleteCommand">A valid SQL statement to delete records from the data source</param>///<param name="updateCommand">A valid SQL statement used to update records in the data source</param>///<param name="dataSet">The DataSet used to update the data source</param>///<param name="tableName">The DataTable used to update the data source.</param>publicstaticvoidUpdateDataset(SQLiteCommand insertCommand, SQLiteCommand deleteCommand, SQLiteCommand updateCommand, DataSet dataSet,stringtableName)
{if(insertCommand==null)thrownewArgumentNullException("insertCommand");if(deleteCommand==null)thrownewArgumentNullException("deleteCommand");if(updateCommand==null)thrownewArgumentNullException("updateCommand");if(tableName==null||tableName.Length==0)thrownewArgumentNullException("tableName");//Create a SQLiteDataAdapter, and dispose of it after we are doneusing(SQLiteDataAdapter dataAdapter=newSQLiteDataAdapter())
{//Set the data adapter commandsdataAdapter.UpdateCommand=updateCommand;
dataAdapter.InsertCommand=insertCommand;
dataAdapter.DeleteCommand=deleteCommand;//Update the dataset changes in the data sourcedataAdapter.Update(dataSet, tableName);//Commit all the changes made to the DataSetdataSet.AcceptChanges();
}
}#endregion///<summary>///ShortCut method to return IDataReader///NOTE: You should explicitly close the Command.connection you passed in as///well as call Dispose on the Command after reader is closed.///We do this because IDataReader has no underlying Connection Property.///</summary>///<param name="cmd">SQLiteCommand Object</param>///<param name="commandText">SQL Statement with optional embedded "@param" style parameters</param>///<param name="paramList">object[] array of parameter values</param>///<returns>IDataReader</returns>publicstaticIDataReader ExecuteReader(SQLiteCommand cmd,stringcommandText,object[] paramList)
{if(cmd.Connection==null)thrownewArgumentException("Command must have live connection attached.","cmd");
cmd.CommandText=commandText;
AttachParameters(cmd,commandText, paramList);if(cmd.Connection.State==ConnectionState.Closed)
cmd.Connection.Open();
IDataReader rdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);returnrdr;
}///<summary>///Shortcut to ExecuteNonQuery with SqlStatement and object[] param values///</summary>///<param name="connectionString">SQLite Connection String</param>///<param name="commandText">Sql Statement with embedded "@param" style parameters</param>///<param name="paramList">object[] array of parameter values</param>///<returns></returns>publicstaticintExecuteNonQuery(stringconnectionString,stringcommandText,paramsobject[] paramList)
{
SQLiteConnection cn=newSQLiteConnection(connectionString);
SQLiteCommand cmd=cn.CreateCommand();
cmd.CommandText=commandText;
AttachParameters(cmd,commandText, paramList);if(cn.State==ConnectionState.Closed)
cn.Open();intresult=cmd.ExecuteNonQuery();
cmd.Dispose();
cn.Close();returnresult;
}publicstaticintExecuteNonQuery(SQLiteConnection cn,stringcommandText,paramsobject[] paramList)
{
SQLiteCommand cmd
=cn.CreateCommand();cmd.CommandText=commandText;
AttachParameters(cmd,commandText, paramList);if(cn.State==ConnectionState.Closed)
cn.Open();intresult=cmd.ExecuteNonQuery();
cmd.Dispose();
cn.Close();returnresult;
}///<summary>///Executes non-query sql Statment with Transaction///</summary>///<param name="transaction">SQLiteTransaction. Transaction consists of Connection, Transaction,///and Command, all of which must be created prior to making this method call.</param>///<param name="commandText">Command text.</param>///<param name="paramList">Param list.</param>///<returns>Integer</returns>///<remarks>user must examine Transaction Object and handle transaction.connection .Close, etc.</remarks>publicstaticintExecuteNonQuery(SQLiteTransaction transaction,stringcommandText,paramsobject[] paramList)
{if(transaction==null)thrownewArgumentNullException("transaction");if(transaction!=null&&transaction.Connection==null)thrownewArgumentException("The transaction was rolled back or committed, please provide an open transaction.","transaction");
IDbCommand cmd=transaction.Connection.CreateCommand();
cmd.CommandText=commandText;
AttachParameters((SQLiteCommand)cmd,cmd.CommandText, paramList);if(transaction.Connection.State==ConnectionState.Closed)
transaction.Connection.Open();intresult=cmd.ExecuteNonQuery();
cmd.Dispose();returnresult;
}///<summary>///Executes the non query.///</summary>///<param name="cmd">CMD.</param>///<returns></returns>publicstaticintExecuteNonQuery(IDbCommand cmd)
{if(cmd.Connection.State==ConnectionState.Closed)
cmd.Connection.Open();intresult=cmd.ExecuteNonQuery();
cmd.Connection.Close();
cmd.Dispose();returnresult;
}///<summary>///Shortcut to ExecuteScalar with Sql Statement embedded params and object[] param values///</summary>///<param name="connectionString">SQLite Connection String</param>///<param name="commandText">SQL statment with embedded "@param" style parameters</param>///<param name="paramList">object[] array of param values</param>///<returns></returns>publicstaticobjectExecuteScalar(stringconnectionString,stringcommandText,paramsobject[] paramList)
{
SQLiteConnection cn=newSQLiteConnection(connectionString);
SQLiteCommand cmd=cn.CreateCommand();
cmd.CommandText=commandText;
AttachParameters(cmd,commandText, paramList);if(cn.State==ConnectionState.Closed)
cn.Open();objectresult=cmd.ExecuteScalar();
cmd.Dispose();
cn.Close();returnresult;
}///<summary>///Execute XmlReader with complete Command///</summary>///<param name="command">SQLite Command</param>///<returns>XmlReader</returns>publicstaticXmlReader ExecuteXmlReader(IDbCommand command)
{//open the connection if necessary, but make sure we//know to close it when we�re done.if(command.Connection.State!=ConnectionState.Open)
{
command.Connection.Open();
}//get a data adapterSQLiteDataAdapter da=newSQLiteDataAdapter((SQLiteCommand)command);
DataSet ds=newDataSet();//fill the data set, and return the schema informationda.MissingSchemaAction=MissingSchemaAction.AddWithKey;
da.Fill(ds);//convert our dataset to XMLStringReader stream=newStringReader(ds.GetXml());
command.Connection.Close();//convert our stream of text to an XmlReaderreturnnewXmlTextReader(stream);
}///<summary>///Parses parameter names from SQL Statement, assigns values from object array ,///and returns fully populated ParameterCollection.///</summary>///<param name="commandText">Sql Statement with "@param" style embedded parameters</param>///<param name="paramList">object[] array of parameter values</param>///<returns>SQLiteParameterCollection</returns>///<remarks>Status experimental. Regex appears to be handling most issues. Note that parameter object array must be in same///order as parameter names appear in SQL statement.</remarks>privatestaticSQLiteParameterCollection AttachParameters(SQLiteCommand cmd,stringcommandText,paramsobject[] paramList)
{if(paramList==null||paramList.Length==0)returnnull;
SQLiteParameterCollection coll
=cmd.Parameters;stringparmString=commandText.Substring(commandText.IndexOf("@"));//pre-process the string so always at least 1 space after a comma.parmString=parmString.Replace(",",",");//get the named parameters into a match collectionstringpattern=@"(@)\S*(.*?)\b";Regex ex=newRegex(pattern, RegexOptions.IgnoreCase);
MatchCollection mc=ex.Matches(parmString);string[] paramNames=newstring[mc.Count];inti=0;foreach(Match minmc)
{
paramNames[i]=m.Value;
i++;
}//now let's type the parametersintj=0;
Type t=null;foreach(objectoinparamList)
{
t=o.GetType();
SQLiteParameter parm
=newSQLiteParameter();switch(t.ToString()){case("DBNull"):case("Char"):case("SByte"):case("UInt16"):case("UInt32"):case("UInt64"):thrownewSystemException("Invalid data type");case("System.String"):
parm.DbType=DbType.String;
parm.ParameterName=paramNames[j];
parm.Value=(string)paramList[j];
coll.Add(parm);break;case("System.Byte[]"):
parm.DbType=DbType.Binary;
parm.ParameterName=paramNames[j];
parm.Value=(byte[])paramList[j];
coll.Add(parm);break;case("System.Int32"):
parm.DbType=DbType.Int32;
parm.ParameterName=paramNames[j];
parm.Value=(int)paramList[j];
coll.Add(parm);break;case("System.Boolean"):
parm.DbType=DbType.Boolean;
parm.ParameterName=paramNames[j];
parm.Value=(bool)paramList[j];
coll.Add(parm);break;case("System.DateTime"):
parm.DbType=DbType.DateTime;
parm.ParameterName=paramNames[j];
parm.Value=Convert.ToDateTime(paramList[j]);
coll.Add(parm);break;case("System.Double"):
parm.DbType=DbType.Double;
parm.ParameterName=paramNames[j];
parm.Value=Convert.ToDouble(paramList[j]);
coll.Add(parm);break;case("System.Decimal"):
parm.DbType=DbType.Decimal;
parm.ParameterName=paramNames[j];
parm.Value=Convert.ToDecimal(paramList[j]);break;case("System.Guid"):
parm.DbType=DbType.Guid;
parm.ParameterName=paramNames[j];
parm.Value=(System.Guid)(paramList[j]);break;case("System.Object"):
parm.DbType
=DbType.Object;parm.ParameterName=paramNames[j];
parm.Value=paramList[j];
coll.Add(parm);break;default:thrownewSystemException("Value is of unknown data type");
}
//end switchj++;}returncoll;
}///<summary>///Executes non query typed params from a DataRow///</summary>///<param name="command">Command.</param>///<param name="dataRow">Data row.</param>///<returns>Integer result code</returns>publicstaticintExecuteNonQueryTypedParams(IDbCommand command, DataRow dataRow)
{intretVal=0;//If the row has values, the store procedure parameters must be initializedif(dataRow!=null&&dataRow.ItemArray.Length>0)
{//Set the parameters valuesAssignParameterValues(command.Parameters, dataRow);
retVal
=ExecuteNonQuery(command);}else{
retVal=ExecuteNonQuery(command);
}returnretVal;
}///<summary>///This method assigns dataRow column values to an IDataParameterCollection///</summary>///<param name="commandParameters">The IDataParameterCollection to be assigned values</param>///<param name="dataRow">The dataRow used to hold the command's parameter values</param>///<exception cref="System.InvalidOperationException">Thrown if any of the parameter names are invalid.</exception>protectedinternalstaticvoidAssignParameterValues(IDataParameterCollection commandParameters, DataRow dataRow)
{if(commandParameters==null||dataRow==null)
{//Do nothing if we get no datareturn;
}
DataColumnCollection columns
=dataRow.Table.Columns;inti=0;//Set the parameters valuesforeach(IDataParameter commandParameterincommandParameters){//Check the parameter nameif(commandParameter.ParameterName==null||commandParameter.ParameterName.Length<=1)thrownewInvalidOperationException(string.Format("Please provide a valid parameter name on the parameter #{0}, the ParameterName property has the following value: '{1}'.",
i, commandParameter.ParameterName));if(columns.Contains(commandParameter.ParameterName))
commandParameter.Value=dataRow[commandParameter.ParameterName];elseif(columns.Contains(commandParameter.ParameterName.Substring(1)))
commandParameter.Value=dataRow[commandParameter.ParameterName.Substring(1)];
i
++;}
}///<summary>///This method assigns dataRow column values to an array of IDataParameters///</summary>///<param name="commandParameters">Array of IDataParameters to be assigned values</param>///<param name="dataRow">The dataRow used to hold the stored procedure's parameter values</param>///<exception cref="System.InvalidOperationException">Thrown if any of the parameter names are invalid.</exception>protectedvoidAssignParameterValues(IDataParameter[] commandParameters, DataRow dataRow)
{if((commandParameters==null)||(dataRow==null))
{//Do nothing if we get no datareturn;
}
DataColumnCollection columns
=dataRow.Table.Columns;inti=0;//Set the parameters valuesforeach(IDataParameter commandParameterincommandParameters){//Check the parameter nameif(commandParameter.ParameterName==null||commandParameter.ParameterName.Length<=1)thrownewInvalidOperationException(string.Format("Please provide a valid parameter name on the parameter #{0}, the ParameterName property has the following value: '{1}'.",
i, commandParameter.ParameterName));if(columns.Contains(commandParameter.ParameterName))
commandParameter.Value=dataRow[commandParameter.ParameterName];elseif(columns.Contains(commandParameter.ParameterName.Substring(1)))
commandParameter.Value=dataRow[commandParameter.ParameterName.Substring(1)];
i
++;}
}///<summary>///This method assigns an array of values to an array of IDataParameters///</summary>///<param name="commandParameters">Array of IDataParameters to be assigned values</param>///<param name="parameterValues">Array of objects holding the values to be assigned</param>///<exception cref="System.ArgumentException">Thrown if an incorrect number of parameters are passed.</exception>protectedvoidAssignParameterValues(IDataParameter[] commandParameters,paramsobject[] parameterValues)
{if((commandParameters==null)||(parameterValues==null))
{//Do nothing if we get no datareturn;
}//We must have the same number of values as we pave parameters to put them inif(commandParameters.Length!=parameterValues.Length)
{thrownewArgumentException("Parameter count does not match Parameter Value count.");
}//Iterate through the IDataParameters, assigning the values from the corresponding position in the//value arrayfor(inti=0, j=commandParameters.Length, k=0; i<j; i++)
{if(commandParameters[i].Direction!=ParameterDirection.ReturnValue)
{//If the current array value derives from IDataParameter, then assign its Value propertyif(parameterValues[k]isIDataParameter)
{
IDataParameter paramInstance;
paramInstance=(IDataParameter)parameterValues[k];if(paramInstance.Direction==ParameterDirection.ReturnValue)
{
paramInstance=(IDataParameter)parameterValues[++k];
}if(paramInstance.Value==null)
{
commandParameters[i].Value=DBNull.Value;
}else{
commandParameters[i].Value=paramInstance.Value;
}
}elseif(parameterValues[k]==null)
{
commandParameters[i].Value=DBNull.Value;
}else{
commandParameters[i].Value=parameterValues[k];
}
k++;
}
}
}
}
}
C# SQLiteHelper类似SqlHelper类实现存取Sqlite数据库相关推荐
- android sqlite 操作类封装,[Android] Sqlite 数据库操做 工具封装类
sqlite 数据库封装类html DatabaseUtil.java(封装的类)java packagecom.jack.androidbase.tools;importandroid.conten ...
- 11 SQLite数据库:启动数据库
1.引入 1.1 引言 要记录高分或者想保存微博,应用就需要存储数据. 在Android世界里,通常可以把数据安全地存放在SQLite数据库中.在这一章中,我们会展示如何创建数据库.如何在数据库中增加 ...
- sqlite数据库的基本增删改查操作
2019独角兽企业重金招聘Python工程师标准>>> 效果图示例 1.在清单里添加相应的权限 <uses-permission android:name="andr ...
- QT读写Sqlite数据库三种方式
QT对一些基本的数据库的访问封装,可谓是极大的方便的我们开发人员,现在我们就来说下QT对Sqlite这个数据库的读写,Sqlite是一个比较小型的本地数据库,对于保存一些软件配置参数或量不是很大的数据 ...
- QT读写Sqlite数据库的三种方式
QT对一些基本的数据库的访问封装,可谓是极大的方便的我们开发人员,现在我们就来说下QT对Sqlite这个数据库的读写,Sqlite是一个比较小型的本地数据库,对于保存一些软件配置参数或量不是很大的数据 ...
- 手把手使用Android自带SQLite数据库(1)—— 建立核心文件
SQLite是一个软件库,实现了自给自足的.无服务器的.零配置的.事务性的 SQL 数据库引擎.详细介绍参见https://www.runoob.com/sqlite/sqlite-intro.htm ...
- Android Studio 使用SQLite数据库来创建数据库+创建数据库表+更新表再次往表添加字段
目录 一.前言 二.SQLite数据库介绍 1.什么是SQLite数据库 2.特点 3.SQLite 操作API 4.SQLite数据类型 三.SQlite数据库的使用 1.创建类继承SQLiteOP ...
- Qt操作SQLite数据库的三种方式
Qt访问Sqlite数据库的三种方式(即使用三种类库去访问),分别为QSqlQuery.QSqlQueryModel.QSqlTableModel,对于这三种类库,可看为一个比一个上层,也就是封装的更 ...
- C# SQLite数据库的帮助类
SQLite帮助类的示例,它包含了常见的数据库操作方法,如打开和关闭数据库连接.执行SQL查询和更新语句.以及获取数据表中的数据等. using System.Data.SQLite;/// < ...
最新文章
- 微软获 OpenAI 独家 GPT-3 模型授权,是潘多拉还是聚宝盆?
- 网络安全 — 安全架构
- mysql 1366in_如何实战解决mysql#1366错误
- 安装部署Exchange Server 2010 CAS NLB MailBox DAG
- 项目管理基础:软件开发的方法介绍
- 对于局部变量_对于SQL常用查询优化方法的整理
- linux ftp 警告暗号话,ssh,FTP到远程服务器时,显示自定义的警告信息
- PDE6 Transport with decay
- 持久层和数据访问层_什么是持久层? JDBC 演变的 Mybatis 架构分析
- 一个很好的开源图像处理软件--imageJ (2
- AT89C51单片机的8位竞赛抢答器的protues仿真设计_倒计时可调
- hive学习第五章:查询
- msf生成windows后门程序
- Java实现分割矩形
- 类和对象6:相关内置函数
- PHP 微信公众号和html5接入微信支付
- Error 3090003: provided keys, permissions, and delays do not satisfy declared authorizations...
- monkey的基本操作命令
- 阿里天池比赛——街景字符编码识别
- 陪伴我成长的学习工作邮箱品牌——TOM邮箱
热门文章
- ROS中base_link, odom, fixed_frame, target_frame和虚拟大地图map的关系
- 【电路】pmic芯片设计细节
- 201771010111李瑞红《面向对象的程序设计》第八周实验总结
- 2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest
- 18.SSM整合_搭建开发环境
- 禁止COOKIE后对SESSION的影响
- 阿里员工离职潮的背后?
- 产品经理入门_所以您想成为产品经理? 这就是我的入门方式。
- npm构建脚本_NPM脚本简介
- 西北工业大学21计算机考研,西北工业大学2018年计算机考研879专业综合考试大纲...