引言

由公司需要使用dapper  同时支持多数据库 又需要支持实体类 又需要支持sql 还需要支持事务 所以采用了 dapper + dapperExtensions  并配套 生成实体类小工具的方式

环境准备

dapper环境

nuget中 下载安装 Dapper, DapperExtensions.NetCore

数据驱动准备

orcale:  Oracle.ManagedDataAccess.Core

SQLite: System.Data.SQLite.Core

日志组件

log4net

Dapper 实体操作简单使用

 var orcalConn = new OracleConnection(strConn);
var orcaleconfig = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new OracleDialect());
var orcaleGenerator = new SqlGeneratorImpl(orcaleconfig);
connection = new Database(orcalConn, orcaleGenerator);

注:数据库不同时 改变 这段内容即可

插入数据使用方式举例:

 Connection.Insert(list, tran, commandTimeout);

针对DapperExtensions简单封装

新建core 类库项目 并引用好所需nuget包

增加以下类

using DapperExtensions.Mapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Text;
using Dapper;
using DapperExtensions;
using System.Reflection;
using DapperExtensions.Sql;
using Oracle.ManagedDataAccess.Client;
using System.Data.SqlClient;
using MySql.Data.MySqlClient; namespace CommonHelper
{
/// <summary>
/// 数据库连接辅助类
/// </summary>
public class ConnectionFactory
{
/// <summary>
/// 转换数据库类型
/// </summary>
/// <param name="databaseType">数据库类型</param>
/// <returns></returns>
public static DatabaseType GetDataBaseType(string databaseType)
{
DatabaseType returnValue = DatabaseType.SqlServer;
foreach (DatabaseType dbType in Enum.GetValues(typeof(DatabaseType)))
{
if (dbType.ToString().Equals(databaseType, StringComparison.OrdinalIgnoreCase))
{
returnValue = dbType;
break;
}
}
return returnValue;
} /// <summary>
/// 获取数据库连接
/// </summary>
/// <returns></returns>
public static Database CreateConnection(string strConn, DatabaseType databaseType = DatabaseType.Oracle)
{
Database connection = null;
//获取配置进行转换
switch (databaseType)
{
case DatabaseType.SqlServer:
var sqlConn = new SqlConnection(strConn);
var sqlconfig = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new SqlServerDialect());
var sqlGenerator = new SqlGeneratorImpl(sqlconfig);
connection = new Database(sqlConn, sqlGenerator);
break;
case DatabaseType.MySql:
var mysqlConn = new MySqlConnection(strConn);
var mysqlconfig = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new MySqlDialect());
var mysqlGenerator = new SqlGeneratorImpl(mysqlconfig);
connection = new Database(mysqlConn, mysqlGenerator);
break;
case DatabaseType.Sqlite:
var sqlliteConn = new SQLiteConnection(strConn);
var sqlliteconfig = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new SqliteDialect());
var sqlliteGenerator = new SqlGeneratorImpl(sqlliteconfig);
connection = new Database(sqlliteConn, sqlliteGenerator);
break;
case DatabaseType.Oracle:
var orcalConn = new OracleConnection(strConn);
var orcaleconfig = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new OracleDialect());
var orcaleGenerator = new SqlGeneratorImpl(orcaleconfig);
connection = new Database(orcalConn, orcaleGenerator);
break;
}
return connection;
}
}
}

ConnectionFactory.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;
using Microsoft.Extensions.Configuration; namespace CommonHelper
{
/// <summary>
/// dapper 帮助类
/// </summary>
public class DapperHelper : IDapperHelper, IDisposable
{
private string ConnectionString = string.Empty;
private Database Connection = null;
/// <summary>
/// 初始化 若不传则默认从appsettings.json读取Connections:DefaultConnect节点
/// 传入setting:xxx:xxx形式 则会从指定的配置文件中读取内容
/// 直接传入连接串则
/// </summary>
/// <param name="conn"></param>
/// <param name="jsonConfigFileName"> 配置文件名称</param>
public DapperHelper(string conn = "", string jsonConfigFileName = "appsettings.json", DatabaseType databaseType = DatabaseType.Oracle)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(jsonConfigFileName, optional: true)
.Build();
if (string.IsNullOrEmpty(conn))
{
conn = config.GetSection("Connections:DefaultConnect").Value;
}
else if (conn.StartsWith("setting:"))
{
conn = config.GetSection(conn.Substring()).Value;
}
ConnectionString = conn;
Connection = ConnectionFactory.CreateConnection(ConnectionString, databaseType);
}
public Database GetConnection()
{
return Connection;
}
public IDbTransaction TranStart()
{
if (Connection.Connection.State == ConnectionState.Closed)
Connection.Connection.Open();
return Connection.Connection.BeginTransaction();
}
public void TranRollBack(IDbTransaction tran)
{
tran.Rollback();
if (Connection.Connection.State == ConnectionState.Open)
tran.Connection.Close();
}
public void TranCommit(IDbTransaction tran)
{
tran.Commit();
if (Connection.Connection.State == ConnectionState.Open)
tran.Connection.Close();
} public bool Delete<T>(T obj, IDbTransaction tran = null, int? commandTimeout = null) where T : class
{ return Connection.Delete(obj, tran, commandTimeout);
} public bool Delete<T>(IEnumerable<T> list, IDbTransaction tran = null, int? commandTimeout = null) where T : class
{ return Connection.Delete(list, tran, commandTimeout);
}
public void Dispose()
{
if (Connection != null)
{
Connection.Dispose();
}
}
public T Get<T>(string id, IDbTransaction tran = null, int? commandTimeout = null) where T : class
{
return Connection.Get<T>(id, tran, commandTimeout);
} public IEnumerable<T> GetAll<T>(object predicate = null, IList<ISort> sort = null, IDbTransaction tran = null, int? commandTimeout = null, bool buffered = true) where T : class
{
return Connection.GetList<T>(predicate, sort, tran, commandTimeout, buffered);
}
public IEnumerable<T> GetPage<T>(object predicate, IList<ISort> sort, int page, int pagesize, IDbTransaction tran = null, int? commandTimeout = null, bool buffered = true) where T : class
{
return Connection.GetPage<T>(predicate, sort, page, pagesize, tran, commandTimeout, buffered);
}
public dynamic Insert<T>(T obj, IDbTransaction tran = null, int? commandTimeout = null) where T : class
{
return Connection.Insert(obj, tran, commandTimeout);
} public void Insert<T>(IEnumerable<T> list, IDbTransaction tran = null, int? commandTimeout = null) where T : class
{
Connection.Insert(list, tran, commandTimeout);
}
public bool Update<T>(T obj, IDbTransaction tran = null, int? commandTimeout = null, bool ignoreAllKeyProperties = true) where T : class
{
return Connection.Update(obj, tran, commandTimeout, ignoreAllKeyProperties);
} public bool Update<T>(IEnumerable<T> list, IDbTransaction tran = null, int? commandTimeout = null, bool ignoreAllKeyProperties = true) where T : class
{
return Connection.Update(list, tran, commandTimeout, ignoreAllKeyProperties);
}
public List<T> Query<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
return Connection.Connection.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType).AsList();
}
public int Execute<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
return Connection.Connection.Execute(sql, param, transaction, commandTimeout, commandType);
}
}
}

DapperHelper.cs

using System;
using System.Collections.Generic;
using System.Text; namespace CommonHelper
{
/// <summary>
/// 数据库类型定义
/// </summary>
public enum DatabaseType
{
SqlServer, //SQLServer数据库
MySql, //Mysql数据库
Oracle, //Oracle数据库
Sqlite, //SQLite数据库
}
}

DatabaseType.cs

using DapperExtensions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks; namespace CommonHelper
{
public interface IDapperHelper
{
Database GetConnection();
T Get<T>(string id, IDbTransaction tran = null, int? commandTimeout = null) where T : class;
IEnumerable<T> GetAll<T>(object predicate = null, IList<ISort> sort = null, IDbTransaction tran = null, int? commandTimeout = null, bool buffered = true) where T : class;
IEnumerable<T> GetPage<T>(object predicate, IList<ISort> sort, int page, int pagesize, IDbTransaction tran = null, int? commandTimeout = null, bool buffered = true) where T : class;
dynamic Insert<T>(T obj,IDbTransaction tran = null, int? commandTimeout = null) where T : class;
void Insert<T>(IEnumerable<T> list, IDbTransaction tran = null, int? commandTimeout = null) where T : class;
bool Update<T>(T obj, IDbTransaction tran = null, int? commandTimeout = null, bool ignoreAllKeyProperties = false) where T : class;
bool Update<T>(IEnumerable<T> list, IDbTransaction tran = null, int? commandTimeout = null, bool ignoreAllKeyProperties = false) where T : class;
bool Delete<T>(T obj, IDbTransaction tran = null, int? commandTimeout = null) where T : class;
bool Delete<T>(IEnumerable<T> list, IDbTransaction tran = null, int? commandTimeout = null) where T : class;
IDbTransaction TranStart();
void TranRollBack(IDbTransaction tran);
void TranCommit(IDbTransaction tran);
List<T> Query<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);
int Execute<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);
}
}

IDapperHelper.cs

using log4net;
using log4net.Config;
using log4net.Repository;
using System;
using System.IO;
//[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)]
namespace CommonHelper
{
public static class LogHelper
{
private static ILoggerRepository repository = LogManager.CreateRepository("ApiLogs");
static LogHelper()
{
XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));
}
private static ILog log = LogManager.GetLogger(repository.Name, "LogHelper");
private static ILog log_Normal = LogManager.GetLogger(repository.Name, "LogHelperNormal");
public static void Write(string msg, LogLev lev)
{
switch (lev)
{
case LogLev.Debug:
log_Normal.Debug(msg);
break;
case LogLev.Error:
log.Error(msg);
break;
case LogLev.Fatal:
log.Fatal(msg);
break;
case LogLev.Info:
log_Normal.Info(msg);
break;
case LogLev.Warn:
log_Normal.Warn(msg);
break;
default:
break;
}
}
public static void Write(string msg, LogLev lev, params object[] parm)
{
switch (lev)
{
case LogLev.Debug:
log_Normal.DebugFormat(msg, parm);
break;
case LogLev.Error:
log.ErrorFormat(msg, parm);
break;
case LogLev.Fatal:
log.FatalFormat(msg, parm);
break;
case LogLev.Info:
log_Normal.InfoFormat(msg, parm);
break;
case LogLev.Warn:
log_Normal.WarnFormat(msg, parm);
break;
default:
break;
}
}
public static void Write(Exception ex, LogLev lev)
{
switch (lev)
{
case LogLev.Debug:
log_Normal.Debug(ex);
break;
case LogLev.Error:
log.Error(ex);
break;
case LogLev.Fatal:
log.Fatal(ex);
break;
case LogLev.Info:
log_Normal.Info(ex);
break;
case LogLev.Warn:
log_Normal.Warn(ex);
break;
default:
break;
}
}
public static void Log(Exception ex)
{
Write("方法:{0} 消息:{1} 类:{2} 堆:{3} ", LogLev.Fatal, ex.TargetSite, ex.Message,ex.Source, ex.StackTrace);
}
public static void Log(Exception ex,int fmodelid)
{
Write("方法:{0} 消息:{1} 类:{2} 堆:{3} fmodelid:{4}", LogLev.Fatal, ex.TargetSite, ex.Message, ex.Source, ex.StackTrace,fmodelid);
}
}
}

LogHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net; namespace CommonHelper
{
public enum LogLev
{
Debug,
Error,
Fatal,
Info,
Warn
}
}

LogLev.cs

引用类库项目后调用方式如下:

在配置文件appsettings.json 中增加

 "Connections": {
"DefaultConnect": "Data Source=192.168.1.xxx/orcl;User ID=xxx;Password=xxxx;"
}
using CommonHelper;
using DapperExtensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Threading.Tasks; namespace DapperHelperTest
{
[TestClass]
public class UnitTest1
{
/// <summary>
/// 基本测试 详细参考https://github.com/tmsmith/Dapper-Extensions/blob/master/DapperExtensions.Test/IntegrationTests/Oracle/CrudFixture.cs
/// </summary>
[TestMethod]
public void TestMethod1()
{
using (var dp = new DapperHelper())
{
var obj = new USER() { FID = "test222", FNAME = "test", FCREATETIME = DateTime.Now, FREALNAME = "t" };
//增
var insert = dp.Insert(obj);
Assert.IsTrue(insert == "test222");
obj.FNAME = "test2";
//改
var update = dp.Update(obj);
Assert.IsTrue(update);
//取所有带条件
var predicate = Predicates.Field<USER>(f => f.FNAME, Operator.Eq, "test2");
var allrecords = dp.GetAll<USER>(predicate);
Assert.IsTrue(allrecords.Count() > );
//取
var user2 = dp.Get<USER>("test222");
Assert.IsTrue(user2 != null);
//删
bool isdel = dp.Delete(obj);
Assert.IsTrue(isdel);
}
}
/// <summary>
/// 测试事务
/// </summary>
[TestMethod]
public void TestMethod2()
{
using (var dp = new DapperHelper())
{
var tran = dp.TranStart();
var obj = new USER() { FID = "test222", FNAME = "test", FCREATETIME = DateTime.Now, FREALNAME = "t" };
//事务回滚
var insert = dp.Insert(obj, tran);
var user2 = dp.Get<USER>("test222", tran);
Assert.IsTrue(user2 != null);
tran.Rollback();
var user3 = dp.Get<USER>("test222");
Assert.IsTrue(user3 == null);
//事务提交
tran = dp.TranStart();
insert = dp.Insert(obj, tran);
Assert.IsTrue(user2 != null);
tran.Commit();
user3 = dp.Get<USER>("test222");
Assert.IsTrue(user3 != null);
//删除测试数据
bool isdel = dp.Delete(obj);
Assert.IsTrue(isdel);
}
}
/// <summary>
/// 测试sql
/// </summary>
[TestMethod]
public void TestMethod3()
{
using (var dp = new DapperHelper())
{
var tt = dp.Query<USER>("select * from USER");
}
} }
}

单元测试示例

注: 需要在引用的项目中增加log4net.config文件 并设置始终复制 或者较新则复制

文件参考如下:

<log4net>
<logger name="LogHelper">
<level value="ALL" />
<appender-ref ref="Appender" />
</logger>
<logger name="LogHelperNormal">
<level value="ALL" />
<appender-ref ref="NormalAppender" />
</logger>
<appender name="Appender" type="log4net.Appender.RollingFileAppender">
<!--日志文件名开头-->
<param name="File" value="Log\\" />
<!--是否追加到文件,默认为true,通常无需设置-->
<param name="AppendToFile" value="true" />
<param name="MaxSizeRollBackups" value="" />
<param name="MaxFileSize" value="" />
<param name="StaticLogFileName" value="false" />
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<param name="DatePattern" value="yyyyMMdd&quot;_Exception.log&quot;" />
<param name="RollingStyle" value="Date" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="&lt;HR COLOR=red&gt;%n异常时间:%d [%t] &lt;BR&gt;%n异常级别:%-5p &lt;BR&gt;%n异 常 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;" />
</layout>
</appender>
<appender name="NormalAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\\" />
<param name="AppendToFile" value="true" />
<param name="MaxFileSize" value="" />
<param name="MaxSizeRollBackups" value="" />
<param name="StaticLogFileName" value="false" />
<param name="DatePattern" value="yyyyMMdd&quot;_Normal.log&quot;" />
<param name="RollingStyle" value="Date" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="&lt;HR COLOR=blue&gt;%n日志时间:%d [%t] &lt;BR&gt;%n日志级别:%-5p &lt;BR&gt;%n日 志 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;" />
</layout>
</appender>
</log4net>

log4net.config

使用sqlsuger 打造简易实体类生成工具

新建core 控制台程序

添加appsettings.json

{
"Connections": {
"DefaultConnect": "Data Source=192.168.1.xxx/orcl;User ID=xxx;Password=xxx;"
},
"Settings": {
"NameSpace": "DBModels",//命名空间
"RelativePath": "AuthService/Models",//相对路径地址
"FullPath": "",//全路径地址 填写以后 相对路径地址失效
"GenerateTables": "USER" //需要生成的表名 不填默认生成全部的表
}
}

改变Program.cs 如下(简易版本 注释部分内容为 继承基类的配置 如需要继承基类 去除注释部分代码即可)

using Microsoft.Extensions.Configuration;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq; namespace ModelGeneration
{
/// <summary>
/// 使用sqlsuger 自动生成实体类
/// </summary>
class Program
{
static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true)
.Build();
var conn = config.GetSection("Connections:DefaultConnect").Value;
string path = string.Empty;
var relativePath = config.GetSection("Settings:RelativePath").Value;
//自动找最外层并 找到更外层 方便附加到其他项目中
if (!string.IsNullOrEmpty(relativePath))
{
var basePath = new DirectoryInfo(Directory.GetCurrentDirectory());
while ((basePath.FullName.Contains(@"\Debug") || basePath.FullName.Contains(@"\bin"))&&!string.IsNullOrEmpty(basePath.FullName))
{
basePath=basePath.Parent;
}
path = Path.Combine(basePath.Parent.FullName, relativePath);
}
var fullPath= config.GetSection("Settings:FullPath").Value;
if (!string.IsNullOrEmpty(fullPath))
path = fullPath;
InitModel(conn,config.GetSection("Settings:NameSpace").Value, path, config.GetSection("Settings:GenerateTables").Value);
}
public static void InitModel(string conn,string namespaceStr, string path,string genaratetables)
{
try
{
Console.WriteLine("开始创建");
var tableNames = genaratetables.Split(',').ToList();
for (int i = ; i < tableNames.Count; i++)
{
tableNames[i] = tableNames[i].ToLower();
}
var suger = GetInstance(conn).DbFirst.SettingClassTemplate(old =>
{
return old.Replace("{Namespace}", namespaceStr);//.Replace("class {ClassName}", "class {ClassName} :BaseEntity");//改变命名空间
});
if (tableNames.Count >= )
{
suger.Where(it => tableNames.Contains(it.ToLower())).IsCreateDefaultValue();
}
else
{
suger.IsCreateDefaultValue();
}
//过滤BaseEntity中存在的字段
//var pros = typeof(BaseEntity).GetProperties();
//var list = new List<SqlSugar.IgnoreColumn>();
var tables = suger.ToClassStringList().Keys;
//foreach (var item in pros)
//{
// foreach (var table in tables)
// {
// list.Add(new SqlSugar.IgnoreColumn() { EntityName = table, PropertyName = item.Name });
// }
//}
//suger.Context.IgnoreColumns.AddRange(list);
suger.CreateClassFile(path);
Console.WriteLine("创建完成");
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static SqlSugarClient GetInstance(string conn)
{
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = conn,
DbType = DbType.Oracle,
IsAutoCloseConnection = true,
IsShardSameThread = true //设为true相同线程是同一个SqlSugarClient
});
db.Ado.IsEnableLogEvent = true;
db.Ado.LogEventStarting = (sql, pars) =>
{ };
return db;
}
}
}

Program.cs

.net core 中简单封装Dapper.Extensions 并使用sqlsuger自动生成实体类的更多相关文章

  1. 使用.net core efcore根据数据库结构自动生成实体类

    源码 github,已更新最新代码 https://github.com/leoparddne/GenEntities/ 使用的DB是mysql,所有先nuget一下mysql.data 创建t4模板 ...

  2. 关于entityframework 自动生成实体类中加验证的属性重新生成后属性被覆盖解决办法

    1.手动创建一个部分类 (你可以手动创建 partial class, 内容为空) [MetadataType(typeof(AppleMetadata))] public partial class ...

  3. idea中自动生成实体类

    找到生成实体的路径,找到Database数据表 找到指定的路径即可自动生成entity实体 在创建好的实体类内如此修改 之后的步骤都在脑子里  写给自己看的东西 哪里不会就记录哪里 test类(以前都 ...

  4. MVC中为自动生成实体类添加验证

    将额外的基于特性的元数据(象验证特性)施加到由VS设计器自动生成/维护的类的一个方法是,采用一个我们称之为“伙伴类(buddy classes)”的技术. 基本上来说,你创建另外一个类,包含你的验证特 ...

  5. Asp.Net Core如何根据数据库自动生成实体类

    通过引用Nuget包添加实体类 运行 Install-Package Microsoft.EntityFrameworkCore.SqlServer 运行 Install-Package Micros ...

  6. 在idea中,mavne项目使用mybatis-generator-maven-plugin自动生成实体了的时候,在maven插件里面始终不显示

    最近想学习mybatis的知识,自己搭了个简单的ssm框架,想通过插件自动生成实体类,发现想要的插件一直都没显示出来,着实很郁闷: pom.xm中的配置: <!--mybatis-generat ...

  7. 【.NetCore学习】ASP.NET Core EF Core2.0 DB First现有数据库自动生成实体Context

    主要参考微软官方文档 https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/existing-db Microsoft .NE ...

  8. .NET平台开源项目速览(20)Newlife.Core中简单灵活的配置文件

    记得5年前开始拼命翻读X组件的源码,特别是XCode,但对Newlife.Core 的东西了解很少,最多只是会用用,而且用到的只是九牛一毛.里面好用的东西太多了. 最近一年时间,零零散散又学了很多,也 ...

  9. .net core 根据数据库生成实体类

    微软最近几年在跨平台上不断发力,很多.net程序员也摩拳擦掌,对微软寄以厚望.就在最近,微软还推出了asp .net core2.0预览版. 通过对.net core的简单尝试,我发现以往我们开发MV ...

随机推荐

  1. gcc的搜索路径,头文件和库

    1 抛开默认的搜索路径,自己指定搜索路径 第一,明确自己编写的代码所需要的头文件和库放在了哪里 第二,使用“-I”指定头文件的搜索路径,使用-rpath指定库的搜索路径 2 无论是本地编译还是交叉编译 ...

  2. 加密散列算法——SHA-1

    与MD5算法类似,SHA-1算法也是在接收到消息后产生消息摘要,能够用来验证数据的完整性. 不同的是SHA1会产生一个160位的消息摘要(MD5产生的是128位). 其它的性质之类的不多说(请參考前面 ...

  3. ios18---自定义控件3改进

    控制器: // XMGViewController.h #import <UIKit/UIKit.h> @interface XMGViewController : UIViewContr ...

  4. Keepalived+lvs 搭建高可用负载均衡

    本站点停止更新,请访问:blog.coocap.com 不了解负载均衡高可用的童鞋,强烈建议先看keepalived+nginx高可用负载均衡: 传送门(求粉):http://www.cnblogs. ...

  5. 【SDOI 2008】 递归数列

    [题目链接] 点击打开链接 [算法] 矩阵乘法优化递推 由于本博客不支持数学公式,所以不能将矩阵画出来,请谅解! [代码] #include<bits/stdc++.h> using na ...

  6. ImportError: No module named flask.ext.login

    from flask.ext.login import current_user python 3.x中,上面代码会报错:ImportError: No module named flask.ext. ...

  7. 第十二周 Leetcode 354. Russian Doll Envelopes(HARD) LIS问题

    Leetcode354 暴力的方法是显而易见的 O(n^2)构造一个DAG找最长链即可. 也有办法优化到O(nlogn) 注意 信封的方向是不能转换的. 对第一维从小到大排序,第一维相同第二维从大到小 ...

  8. bzoj 2100: [Usaco2010 Dec]Apple Delivery【spfa】

    洛谷数据好强啊,普通spfa开o2都过不了,要加双端队列优化 因为是双向边,所以dis(u,v)=dis(v,u),所以分别以pa1和pa2为起点spfa一遍,表示pb-->pa1-->p ...

  9. P4727 [HNOI2009]图的同构记数

    传送门 如果我们把选出子图看成选出边,进而看成对边黑白染色,那么就是上一题的弱化版了,直接复制过来然后令\(m=2\)即可 不过直接交上去会T,于是加了几发大力优化 不知为何华丽的被小号抢了rank2 ...

  10. [App Store Connect帮助]六、测试 Beta 版本(1)TestFlight Beta 版测试概述(iOS、Apple TVOS、watchOS)

    TestFlight Beta 版测试让您可以分发您 App 的 Beta 版构建版本给测试员并收集反馈.您可以在您的 App Store Connect 帐户中一次为至多 100 个 App 启用 ...