对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。

在今日的企业环境中,把面向对象软件和关系数据库一起使用可能是相当麻烦和浪费时间的,ORM

 

不仅仅管理.NET类到数据库表的映射(包括.NET 数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和ADO.NET处理数据的时间。

现在有很多成熟的开源框架支持ORM,如:NHibernate,PDO....等 但是他们内部是怎么实现的, 通过一个非常简单的实例让我们一起来探索其中最为关键的过程. (适合ORM初学者)我们以Sql Server 为例

定义操作类型枚举, 为增强可读性 将枚举名使用中文,在实际应用中不建议使用中文作为枚举名称。

  1. public class DataMessageClass
  2. {
  3. public enum DataMessage
  4. {
  5. 数据连接失败,系统忙请等待,操作成功,可继续操作
  6. }
  7. }

标记实体映射基类

  1. /// <summary>
  2. /// DataBase 的摘要说明。
  3. /// </summary>
  4. public interface IDataBase
  5. {
  6. }

自定义属性类,DataObjectAttribute 用于标记映射实体所对应的数据表 FieldObjectAttribute用于标记字段所代表的特殊属性

需要的对数据库表和字段的简单表示我们都有了,下一步来实现对Sql Server 数据表的,Select ,Update,Insert 等操作,ORM映射实现类。

 public class DataAccess
{
private static string mConnectStr=string.Empty;
private static System.Data.SqlClient.SqlConnection mSqlConnect; //连接
private static System.Data.SqlClient.SqlCommand mSqlCmd; // 执行命令
private static System.Data.SqlClient.SqlDataAdapter mDataAdapter; //装配件
private const string mConnectKey="TestConnect"; // 数据库连接字符串键名
public DataAccess()
{
try
{
//
// TODO: 在此处添加构造函数逻辑
//
mConnectStr=GetConnectValue();
mSqlConnect= new SqlConnection(mConnectStr);
mSqlConnect.Open();
}
catch
{
mSqlConnect= new SqlConnection(mConnectStr);
}
}
public void Close()
{
if (mSqlConnect != null && mSqlConnect.State != ConnectionState.Closed)
{
mSqlConnect.Close();
}
}
/// <summary>
/// 初始化数据连接对象
/// </summary>
/// <param name="ConnectStr"></param>
public DataAccess(string ConnectStr)
{
//
// TODO: 在此处添加构造函数逻辑
//
mConnectStr=ConnectStr;
mSqlConnect= new SqlConnection(mConnectStr);
mSqlConnect.Open();
}
/// <summary>
/// 获得连接字符串的值
/// </summary>
/// <returns></returns>
private string GetConnectValue()
{
return System.Configuration.ConfigurationSettings.AppSettings[mConnectKey].ToString();
}
private DataMessageClass.DataMessage CheckOpenState()
{
if(mSqlConnect.State==System.Data.ConnectionState.Broken || mSqlConnect.State==System.Data.ConnectionState.Closed)
{
mSqlConnect.Close();
mSqlConnect.ConnectionString = mConnectStr;
try
{
lock(mSqlConnect)
{
mSqlConnect.Open();
}
}
catch(System.Exception ex)
{
return DataMessageClass.DataMessage.数据连接失败;
}
}
if(mSqlConnect.State==System.Data.ConnectionState.Executing || mSqlConnect.State==System.Data.ConnectionState.Fetching || mSqlConnect.State==System.Data.ConnectionState.Connecting)
{
return DataMessageClass.DataMessage.系统忙请等待;
}
return DataMessageClass.DataMessage.可继续操作;
}
/// <summary>
/// 执行Sql语句 带参数
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <param name="ExeSqlParameter">参数</param>
/// <returns></returns>
public DataMessageClass.DataMessage ExeSQL(string ExeSqlStr,System.Data.SqlClient.SqlParameter[] ExeSqlParameter)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in ExeSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);}
}
mSqlCmd.ExecuteNonQuery();
}
return DataMessageClass.DataMessage.操作成功;
}
/// <summary>
/// 执行Sql语句 不带参数
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <returns></returns>
public DataMessageClass.DataMessage ExeSQL(string ExeSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
mSqlCmd.ExecuteNonQuery();
}
return DataMessageClass.DataMessage.操作成功;
}
/// <summary>
/// 执行Sql语句 不带参数 返回一个值
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <returns></returns>
public object ExeSQLReturnValue(string ExeSqlStr,System.Data.SqlClient.SqlParameter[] ExeSqlParameter)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in ExeSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);};
}
return mSqlCmd.ExecuteScalar();
}
return null;
}
/// <summary>
/// 执行Sql语句 不带参数 返回一个值
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <returns></returns>
public object ExeSQLReturnValue(string ExeSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
return mSqlCmd.ExecuteScalar();
}
return null;
}
/// <summary>
/// 获得查询表记录 带参数
/// </summary>
/// <param name="SelSqlStr">语句</param>
/// <param name="SelSqlParameter">参数</param>
/// <returns>数据集合</returns>
public System.Data.DataSet GetSelectRow(string SelSqlStr,System.Data.SqlClient.SqlParameter[] SelSqlParameter)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SelSqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in SelSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);};
}
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet);
return TempDataSet;
}
return null;
}
/// <summary>
/// 获得查询表记录 不带参数
/// </summary>
/// <param name="SelSqlStr">语句</param>
/// <returns>set数据集合</returns>
public System.Data.DataSet GetSelectRow(string SelSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SelSqlStr,mSqlConnect);
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet);
return TempDataSet;
}
return null;
}
/// <summary>
/// 获得查询表记录 不带参数
/// </summary>
/// <param name="SelSqlStr">语句</param>
/// <returns>Reader数据集合</returns>
public System.Data.SqlClient.SqlDataReader GetSelectRowReader(string SelSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SelSqlStr,mSqlConnect);
// 装入数据
System.Data.SqlClient.SqlDataReader TDataReader;
TDataReader=mSqlCmd.ExecuteReader();
return TDataReader;
}
return null;
}
/// <summary>
/// 分页读取
/// </summary>
/// <param name="SqlStr">语句</param>
/// <param name="SelSqlParameter">参数</param>
/// <param name="DataSetName">名称</param>
/// <param name="PageIndex">当前页面</param>
/// <param name="MaxReocrd">记录数</param>
/// <returns></returns>
public System.Data.DataSet GetPageDataSet(string SqlStr,System.Data.SqlClient.SqlParameter[] SelSqlParameter,string DataSetName,int PageIndex,int MaxReocrd)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in SelSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);};
}
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet,(PageIndex-) * MaxReocrd, MaxReocrd,DataSetName);
return TempDataSet;
}
return null;
}
/// <summary>
/// 分页读取 不带参数
/// </summary>
/// <param name="SqlStr">语句</param>
/// <param name="SelSqlParameter">参数</param>
/// <param name="DataSetName">名称</param>
/// <param name="PageIndex">当前页面</param>
/// <param name="MaxReocrd">记录数</param>
/// <returns></returns>
public System.Data.DataSet GetPageDataSet(string SqlStr,string DataSetName,int PageIndex,int MaxReocrd)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SqlStr,mSqlConnect);
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet,(PageIndex-) * MaxReocrd, MaxReocrd,DataSetName);
return TempDataSet;
}
return null;
}
/// <summary>
/// 获得一个对象
/// </summary>
/// <param name="TDataBase"></param>
public IDataBase GetOnlyObject(IDataBase TDataBase)
{
// 生成条件
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[KeyS.Length];
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
string SelSql="Select * From " + TableName + " ";
for (byte index=; index<KeyS.Length;index++)
{
if (index==)
SelSql += " Where " + KeyS[index] + " = @" + KeyS[index] + " " ;
else
SelSql += " and " + KeyS[index] + " = @" + KeyS[index] + " " ;
TSqlParameter[index]=new SqlParameter("@" + KeyS[index] ,TDataBase.GetType().GetField(KeyS[index]).GetValue(TDataBase));
}
// 得到记录
System.Data.DataSet TDataSet= new DataSet();
TDataSet=GetSelectRow(SelSql,TSqlParameter);
if (TDataSet.Tables[].Rows.Count ==) {return null;}
// 把数据分配到字段
foreach (System.Reflection.FieldInfo TFieldInfo in mFieldInfo)
{
TDataBase.GetType().GetField(TFieldInfo.Name).SetValue(TDataBase,TDataSet.Tables[].Rows[][TFieldInfo.Name]==System.DBNull.Value ? GetTypeValue(TFieldInfo.FieldType) :TDataSet.Tables[].Rows[][TFieldInfo.Name]);
}
return TDataBase;
}
/// <summary>
/// 得到初始值
/// </summary>
/// <param name="TType"></param>
/// <returns></returns>
private object GetTypeValue(System.Type TType)
{
if(TType.FullName.Equals(System.TypeCode.DateTime.GetType()))
{
return System.DateTime.Now;
}
return null;
}
/// <summary>
/// 添加一个对象
/// </summary>
/// <param name="TDataBase"></param>
public object AddOnlyObjectReturnIndex(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[mFieldInfo.Length];
string SelSql="insert into " + TableName + " ";
string FieldName =string.Empty;
string ValueName =string.Empty;
for (byte index= ; index <mFieldInfo.Length ; index ++)
{
if(mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false).Length!=)
{
FieldObjectAttribute TFieldObject =mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false)[] as FieldObjectAttribute;
if (TFieldObject.Type==)
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,System.Guid.NewGuid().ToString());
}
else if (TFieldObject.Type==)
{
// 此字段为自增列放弃
}
}
else
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
SelSql += " (" + FieldName + ") VALUES (" + ValueName + ") SELECT @@IDENTITY AS 'Identity'";
return ExeSQLReturnValue(SelSql,TSqlParameter);
}
/// <summary>
/// 添加一个对象
/// </summary>
/// <param name="TDataBase"></param>
public void AddOnlyObject(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[mFieldInfo.Length];
string SelSql="insert into " + TableName + " ";
string FieldName =string.Empty;
string ValueName =string.Empty;
for (byte index= ; index <mFieldInfo.Length ; index ++)
{
if(mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false).Length!=)
{
FieldObjectAttribute TFieldObject =mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false)[] as FieldObjectAttribute;
if (TFieldObject.Type==)
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,System.Guid.NewGuid().ToString());
}
else if (TFieldObject.Type==)
{
// 此字段为自增列放弃
}
}
else
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
SelSql += " (" + FieldName + ") VALUES (" + ValueName + ")";
ExeSQL(SelSql,TSqlParameter);
}
/// <summary>
/// 更新一个对象
/// </summary>
/// <param name="TDataBase"></param>
public void UpdateOnlyObject(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
Array TArray = Array.CreateInstance(typeof(string),KeyS.Length);
KeyS.CopyTo(TArray,);
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[mFieldInfo.Length];
string SelSql="Update " + TableName + " Set ";
string FieldValueName =string.Empty;
string WhereName = string.Empty;
for (byte index= ; index <mFieldInfo.Length ; index ++)
{
if(mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false).Length!=)
{
FieldObjectAttribute TFieldObject =mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false)[] as FieldObjectAttribute;
if (TFieldObject.Type==)
{
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
else
{
if(Array.IndexOf(TArray,mFieldInfo[index].Name)==-)
{
FieldValueName += FieldValueName.Length > ? ", " + mFieldInfo[index].Name + "=@" + mFieldInfo[index].Name : mFieldInfo[index].Name + "=@" + mFieldInfo[index].Name;
}
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
for (byte index=; index<KeyS.Length;index++)
{
WhereName += WhereName.Length> ? " and " + KeyS[index] + " = @" + KeyS[index] :" Where " + KeyS[index] + " = @" + KeyS[index] ;
}
SelSql += FieldValueName + WhereName;
ExeSQL(SelSql,TSqlParameter);
}
/// <summary>
/// 删除一个对象
/// </summary>
/// <param name="TDataBase"></param>
public void DelOnlyObject(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[KeyS.Length];
string SelSql="delete " + TableName ;
string FieldValueName =string.Empty;
for (byte index=; index<KeyS.Length;index++)
{
FieldValueName += FieldValueName.Length> ? " and " + KeyS[index] + " = @" + KeyS[index] :" Where " + KeyS[index] + " = @" + KeyS[index] ;
TSqlParameter[index]=new SqlParameter("@" + KeyS[index] ,TDataBase.GetType().GetField(KeyS[index]).GetValue(TDataBase));
}
SelSql+=FieldValueName;
ExeSQL(SelSql,TSqlParameter);
}
}
 

实现就这么简单了,让我们测试其使用过程。

第一步:定义数据映射实体

 /// <summary>
/// "UserInfo" 标示目标表名
/// "Guid" 代表主键, 可以通过逗号分隔来指定多个主键
/// </summary>
[DataAccess.DataObject("UserInfo", "Guid")]
public class UserInfo : IDataBase
{
/// <summary>
/// FieldObject(0) 标示GUID 类型的主键,FieldObject(1) 标示自增性主键
/// </summary>
[FieldObject()]
public string Guid = string.Empty;
public string UserName = string.Empty;
public string UserEMail = string.Empty;
public string UserTel = string.Empty;
public string UserSex = string.Empty;
public string UserDec = string.Empty;
public string RegIpAddres = string.Empty;
}

第二步:配置连接字符串

 <appSettings>
<add key ="ORMConnect" value ="Data Source=???.??.??.???,1433;Initial Catalog=?????;Persist Security Info=True;User ID=?????;Password=??????"/>
</appSettings >

第三步:测试对数据表的操作

 [c-sharp] view plaincopyprint?

 DataAccess.DataAccess ormAccess= new DataAccess.DataAccess();

 UserInfo info = new UserInfo();
info.UserName = "TestUser" ; info.UserDec = http://www.apace.com.cn; info.UserEMail = G_Jack@.com;
info.UserTel = "";
info.RegIpAddres = “testip”; //测试新增 ormAccess.AddOnlyObject(info); //测试更新 ormAccess.UpdateOnlyObject(info) //测试删除 ormAccess.DelOnlyObject(info)

对ORM的简单实现就到处结束了,希望能帮到大家

C# ORM简单原理的更多相关文章

  1. java中异常处理机制的简单原理

    以上是自认为的java异常处理的简单原理,如有不妥之处还请各位大神帮忙指点,谢谢!

  2. java——关于异常处理机制的简单原理和应用

    异常处理机制的简单原理和应用 一.Execption可以分为java标准定义的异常和程序员自定义异常2种 (1)一种是当程序违反了java语规则的时候,JAVA虚拟机就会将发生的错误表示为一个异常.这 ...

  3. javascript AJAX简单原理及什么是ajax

    AJAX简单原理供初学者理解 AJAX的原理: Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面.这其 ...

  4. ORM实现原理

    1.什么是ORM ORM的全称是Object Relational Mapping,即对象关系映射.它的实现思想就是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的 ...

  5. js编译器的一些简单原理

    有没有发现在写代码的时候,往往会遇到一些莫名其妙的错误,然后时间紧急不得不去网上查阅一些代码.虽然要实现的功能解决了,但是看被拷贝的代码好多真心看不懂,以后遇到诸如此类的问题,如果查阅不到这些代码的话 ...

  6. 为初学者写ORM,ORM的原理及测试案例

    提纲 一.什么是ORM.二.反射以及Attribute在ORM中的应用.三.创建一个数据库表和表对应的实体model.四.实体model如何映射出数据库表.五.组合ORM映射生成insert语句.六. ...

  7. Spring MVC简单原理

    Spring MVC原理 针对有Java Web基础.Spring基础和Spring MVC使用经验者. 前言 目前基于Java的web后端,Spring生态应该是比较常见了.虽然现在流行前后端分离, ...

  8. Android开发学习之路--RxAndroid之简单原理

      学习了RxAndroid,其实也就是RxJava了,但是还是不是非常清楚到底RxAndroid有什么用呢?为什么要使用RxAndroid呢?这篇文章讲得不错,RxJava的原理.但是这里还是把整个 ...

  9. go 利用orm简单实现接口分布式锁

    在开发中有些敏感接口,例如用户余额提现接口,需要考虑在并发情况下接口是否会发生问题.如果用户将自己的多条提现请求同时发送到服务器,代码能否扛得住呢?一旦没做锁,那么就真的会给用户多次提现,给公司带来损 ...

随机推荐

  1. QT使用MySql的配置(使用addLibraryPath载入插件),编译QT的MySql驱动问题及解决方案(自己使用libmysql.lib进行编译mysql.pro,万不得已可以查看Makefile.Debug以解决问题)

    2010/04/23:Fixes : 更新批处理,以兼容WIN7. 第一次系统地玩QT,于是诞生了此预备式: [QT版本4.6.0(VS2008编译版),开发平台推荐使用Qt Creator(最新1. ...

  2. BFS提高效率的一点建议

    BFS有两种常见的形式: 形式1: 把初始点加入队列; while (队列非空) { 取出队头; 操作取出的点; 寻找周围符合条件的点加入队列; } 形式2: 操作初始点 把初始点加入队列; whil ...

  3. .NET中扩展方法和Enumerable(System.Linq)

    LINQ是我最喜欢的功能之一,程序中到处是data.Where(x=x>5).Select(x)等等的代码,她使代码看起来更好,更容易编写,使用起来也超级方便,foreach使循环更加容易,而不 ...

  4. 使用LinkedList模拟一个堆栈或者队列数据结构。

    堆栈:先进后出 First in last out filo 队列:先进先出 First in last out filo使用LinkedList的方法,addFirst addLast getFir ...

  5. Babel是什么?

    要是官方文档写得好的话,我也许就不用自己做个笔记. 官方文档 Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运 ...

  6. 04-MySQL中的数据类型

    1 整体说明MYsql的数据类型#1. 数字:    整型:tinyint  int  bigint    小数:        float :在位数比较短的情况下不精准        double ...

  7. MySQL8.0 DDL原子性特性

    1. DDL原子性概述 8.0之前并没有统一的数据字典dd,server层和引擎层各有一套元数据,sever层的元数据包括(.frm,.opt,.par,.trg等),用于存储表定义,分区表定义,触发 ...

  8. C# 位运算及实例计算

    前言: 平时在实际工作中很少用到这个,虽然都是一些比较基础的东西,但一旦遇到了,又不知所云.刚好最近接触了一些相关这方面的项目,所以也算是对 这些内容重新温习实践了一遍.所以这篇不仅作为个人备忘,也分 ...

  9. 该如何真正进入SEO行业?

    今天一个多年的朋友突然问我这个问题,他作为一个seo局外人,感觉SEO挺神秘,我认为要入行就要先了解一个SEO是什么职业,它的工作有那些,然后再考虑怎样进行学习或培训. 一.查看网站状态 seo人员每 ...

  10. mysql复制那点事 - Seconds_behind_Master参数调查笔记

    目录 mysql复制那点事 - Seconds_behind_Master参数调查笔记 0. 参考文献 1. 问题背景 2. 调查结论 3. 调查与分析过程 3.1 轮转binlog时的运行逻辑 3. ...