Dapper 简介

Dapper是.NET的一款轻量级ORM工具(GitHub),也可称为简单对象映射器。在速度方面拥有微型ORM之王的称号。

它是半自动的,也就是说实体类和SQL语句都要自己写,但它提供自动对象映射。是通过对IDbConnection接口的扩展来操作数据库的。

优点

  • 轻量,只有一个文件
  • 性能高,Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
  • 支持多种数据库。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
  • 使用Dapper可以自动进行对象映射,通过Emit反射IDataReader的序列队列,来快速的得到和产生对象

使用 Dapper

下面简单创建一个Web API应用并通过Dapper访问MySQL数据。

  1. 创建MySQL测试数据

    CREATE SCHEMA `ormdemo` ;
    
    CREATE TABLE `ormdemo`.`category` (
    `Id` INT NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(45) NOT NULL,
    PRIMARY KEY (`Id`)); CREATE TABLE `ormdemo`.`product` (
    `Id` INT NOT NULL AUTO_INCREMENT,
    `Name` VARCHAR(45) NOT NULL,
    `Price` DECIMAL(19,2) NULL,
    `Quantity` INT NULL,
    `CategoryId` INT NOT NULL,
    PRIMARY KEY (`Id`),
    INDEX `fk_product_category_idx` (`CategoryId` ASC),
    CONSTRAINT `fk_product_category`
    FOREIGN KEY (`CategoryId`)
    REFERENCES `ormdemo`.`category` (`Id`)
    ON DELETE CASCADE
    ON UPDATE NO ACTION); INSERT INTO `ormdemo`.`category` (`Name`) VALUES("Phones");
    INSERT INTO `ormdemo`.`category` (`Name`) VALUES("Computers"); INSERT INTO `ormdemo`.`product` (`Name`,`Price`,`Quantity`,`CategoryId`) VALUES("iPhone8",4999.99,10,1);
    INSERT INTO `ormdemo`.`product` (`Name`,`Price`,`Quantity`,`CategoryId`) VALUES("iPhone7",2999.99,10,1);
    INSERT INTO `ormdemo`.`product` (`Name`,`Price`,`Quantity`,`CategoryId`) VALUES("HP750",6000.00,5,2);
    INSERT INTO `ormdemo`.`product` (`Name`,`Price`,`Quantity`,`CategoryId`) VALUES("HP5000",12000.00,10,2);
  2. 创建Web API应用并添加NuGet引用

    Install-Package MySql.Data
    Install-Package Dapper
  3. 新建一个Product类

    public class Category
    {
    public int Id { get; set; } public string Name { get; set; }
    } public class Product
    {
    public int Id { get; set; } public string Name { get; set; } public int Quantity { get; set; } public decimal Price { get; set; } public int CategoryId { get; set; } public virtual Category Category { get; set; }
    }
  4. 新建一个DBConfig类用于创建并返回数据库连接

    using MySql.Data.MySqlClient;
    using System.Data;
    using System.Configuration; public class DBConfig
    {
    //ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
    private static string DefaultSqlConnectionString = @"server=127.0.0.1;database=ormdemo;uid=root;pwd=Open0001;SslMode=none;"; public static IDbConnection GetSqlConnection(string sqlConnectionString = null)
    {
    if (string.IsNullOrWhiteSpace(sqlConnectionString))
    {
    sqlConnectionString = DefaultSqlConnectionString;
    }
    IDbConnection conn = new MySqlConnection(sqlConnectionString);
    conn.Open();
    return conn;
    }
    }
  5. 创建简单的仓储接口和类

    public interface IProductRepository
    {
    Task<bool> AddAsync(Product prod);
    Task<IEnumerable<Product>> GetAllAsync();
    Task<Product> GetByIDAsync(int id);
    Task<bool> DeleteAsync(int id);
    Task<bool> UpdateAsync(Product prod);
    }
    public class ProductRepository : IProductRepository
    {
    public async Task<IEnumerable<Product>> GetAllAsync()
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    return await conn.QueryAsync<Product>(@"SELECT Id
    ,Name
    ,Quantity
    ,Price
    ,CategoryId
    FROM Product");
    }
    } public async Task<Product> GetByIDAsync(int id)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    string sql = @"SELECT Id
    ,Name
    ,Quantity
    ,Price
    ,CategoryId
    FROM Product
    WHERE Id = @Id";
    return await conn.QueryFirstOrDefaultAsync<Product>(sql, new { Id = id });
    }
    } public async Task<bool> AddAsync(Product prod)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    string sql = @"INSERT INTO Product
    (Name
    ,Quantity
    ,Price
    ,CategoryId)
    VALUES
    (@Name
    ,@Quantity
    ,@Price
    ,@CategoryId)";
    return await conn.ExecuteAsync(sql, prod) > 0;
    }
    } public async Task<bool> UpdateAsync(Product prod)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    string sql = @"UPDATE Product SET
    Name = @Name
    ,Quantity = @Quantity
    ,Price= @Price
    ,CategoryId= @CategoryId
    WHERE Id = @Id";
    return await conn.ExecuteAsync(sql, prod) > 0;
    }
    } public async Task<bool> DeleteAsync(int id)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    string sql = @"DELETE FROM Product
    WHERE Id = @Id";
    return await conn.ExecuteAsync(sql, new { Id = id }) > 0;
    }
    }
    }

    在Startup ConfigureServices方法里面配置依赖注入

    public void ConfigureServices(IServiceCollection services)
    {
    services.AddTransient<IProductRepository, ProductRepository>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
  6. 在Controller里面调用仓储方法

    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
    private readonly IProductRepository _productRepository;
    public ProductController(IProductRepository productRepository)
    {
    _productRepository = productRepository;
    } [HttpGet]
    public async Task<IActionResult> Get()
    {
    var data = await _productRepository.GetAllAsync();
    return Ok(data);
    } [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
    var data = await _productRepository.GetByIDAsync(id);
    return Ok(data);
    } [HttpPost]
    public async Task<IActionResult> Post([FromBody] Product prod)
    {
    if (!ModelState.IsValid)
    {
    return BadRequest(ModelState);
    } await _productRepository.AddAsync(prod);
    return NoContent();
    } [HttpPut("{id}")]
    public async Task<IActionResult> Put(int id, [FromBody] Product prod)
    {
    if (!ModelState.IsValid)
    {
    return BadRequest(ModelState);
    } var model = await _productRepository.GetByIDAsync(id);
    model.Name = prod.Name;
    model.Quantity = prod.Quantity;
    model.Price = prod.Price;
    await _productRepository.UpdateAsync(model); return NoContent();
    } [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(int id)
    {
    await _productRepository.DeleteAsync(id);
    return NoContent();
    }
    }
  7. 测试API是否可以正常工作

  8. Dapper对存储过程和事务的支持

    存储过程

    using (var connection = My.ConnectionFactory())
    {
    connection.Open(); var affectedRows = connection.Execute(sql,
    new {Kind = InvoiceKind.WebInvoice, Code = "Single_Insert_1"},
    commandType: CommandType.StoredProcedure); My.Result.Show(affectedRows);
    }

    事务

    using (var connection = My.ConnectionFactory())
    {
    connection.Open(); using (var transaction = connection.BeginTransaction())
    {
    var affectedRows = connection.Execute(sql, new {CustomerName = "Mark"}, transaction: transaction); transaction.Commit();
    }
    }
  9. Dapper对多表映射的支持

    var selectAllProductWithCategorySQL = @"select * from product p
    inner join category c on c.Id = p.CategoryId
    Order by p.Id";
    var allProductWithCategory = connection.Query<Product, Category, Product>(selectAllProductWithCategorySQL, (prod, cg) => { prod.Category = cg; return prod; });

使用 Dapper Contrib 或其他扩展

Dapper Contrib扩展Dapper提供了CRUD的方法

  • Get
  • GetAll
  • Insert
  • Update
  • Delete
  • DeleteAll
  1. 添加NuGet引用Dapper.Contrib

    Install-Package Dapper.Contrib
  2. 为Product类添加数据注解

    [Table("Product")]
    public class Product
    {
    [Key]
    public int Id { get; set; } public string Name { get; set; } public int Quantity { get; set; } public decimal Price { get; set; } public int CategoryId { get; set; } public virtual Category Category { get; set; }
    }
  3. 增加一个新的仓储类继承

    public class ContribProductRepository : IProductRepository
    {
    public async Task<bool> AddAsync(Product prod)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    return await conn.InsertAsync(prod) > 0;
    }
    } public async Task<IEnumerable<Product>> GetAllAsync()
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    return await conn.GetAllAsync<Product>();
    }
    } public async Task<Product> GetByIDAsync(int id)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    return await conn.GetAsync<Product>(id);
    }
    } public async Task<bool> DeleteAsync(int id)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    var entity = await conn.GetAsync<Product>(id);
    return await conn.DeleteAsync(entity);
    }
    } public async Task<bool> UpdateAsync(Product prod)
    {
    using (IDbConnection conn = DBConfig.GetSqlConnection())
    {
    return await conn.UpdateAsync(prod);
    }
    }
    }

    修改Startup ConfigureServices方法里面配置依赖注入

    services.AddTransient<IProductRepository, ContribProductRepository>();

    测试,这样可以少写了不少基本的SQL语句。

  4. 其他一些开源的Dapper扩展

    类库 提供的方法
    Dapper.SimpleCRUD Get GetList GetListPaged Insert Update Delete DeleteList RecordCount
    Dapper Plus Bulk Insert Bulk Delete Bulk Update Bulk Merge Bulk Action Async Bulk Also Action Bulk Then Action
    Dapper.FastCRUD Get Find Insert Update BulkUpdate Delete BulkDelete Count
    Dapper.Mapper Multi-mapping

引入工作单元 Unit of Work

仓储模式往往需要工作单元模式的介入来负责一系列仓储对象的持久化,确保数据完整性。网上关于工作单元模式的实现方式有多种,但其本质都是工作单元类通过创建一个所有仓储共享的数据库上下文对象,来组织多个仓储对象。

网上的一些实现方式:

  • Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application

    微软之前给出的一个示例,仓储类做为工作单元的变量,并通过工作单元传入一致的context参数创建。

    public class UnitOfWork : IDisposable
    {
    private SchoolContext context = new SchoolContext();
    private GenericRepository<Department> departmentRepository;
    private GenericRepository<Course> courseRepository; public GenericRepository<Department> DepartmentRepository
    {
    get
    { if (this.departmentRepository == null)
    {
    this.departmentRepository = new GenericRepository<Department>(context);
    }
    return departmentRepository;
    }
    } public GenericRepository<Course> CourseRepository
    {
    get
    { if (this.courseRepository == null)
    {
    this.courseRepository = new GenericRepository<Course>(context);
    }
    return courseRepository;
    }
    } public void Save()
    {
    context.SaveChanges();
    } private bool disposed = false; protected virtual void Dispose(bool disposing)
    {
    if (!this.disposed)
    {
    if (disposing)
    {
    context.Dispose();
    }
    }
    this.disposed = true;
    } public void Dispose()
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }
    }
  • DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践

    博客园一位大神的总结,最终采用的方案是仓储类负责查询,工作单元类负责增删改等数据持久化操作。

优缺点不作讨论,适合自己的就是最好的,这里采用了另外一种实现方式:

  • 定义DapperDBContext

    public interface IContext : IDisposable
    {
    bool IsTransactionStarted { get; } void BeginTransaction(); void Commit(); void Rollback();
    } public abstract class DapperDBContext : IContext
    {
    private IDbConnection _connection;
    private IDbTransaction _transaction;
    private int? _commandTimeout = null;
    private readonly DapperDBContextOptions _options; public bool IsTransactionStarted { get; private set; } protected abstract IDbConnection CreateConnection(string connectionString); protected DapperDBContext(IOptions<DapperDBContextOptions> optionsAccessor)
    {
    _options = optionsAccessor.Value; _connection = CreateConnection(_options.Configuration);
    _connection.Open(); DebugPrint("Connection started.");
    } #region Transaction public void BeginTransaction()
    {
    if (IsTransactionStarted)
    throw new InvalidOperationException("Transaction is already started."); _transaction = _connection.BeginTransaction();
    IsTransactionStarted = true; DebugPrint("Transaction started.");
    } public void Commit()
    {
    if (!IsTransactionStarted)
    throw new InvalidOperationException("No transaction started."); _transaction.Commit();
    _transaction = null; IsTransactionStarted = false; DebugPrint("Transaction committed.");
    } public void Rollback()
    {
    if (!IsTransactionStarted)
    throw new InvalidOperationException("No transaction started."); _transaction.Rollback();
    _transaction.Dispose();
    _transaction = null; IsTransactionStarted = false; DebugPrint("Transaction rollbacked and disposed.");
    } #endregion Transaction #region Dapper Execute & Query public async Task<int> ExecuteAsync(string sql, object param = null, CommandType commandType = CommandType.Text)
    {
    return await _connection.ExecuteAsync(sql, param, _transaction, _commandTimeout, commandType);
    } public async Task<IEnumerable<T>> QueryAsync<T>(string sql, object param = null, CommandType commandType = CommandType.Text)
    {
    return await _connection.QueryAsync<T>(sql, param, _transaction, _commandTimeout, commandType);
    } public async Task<T> QueryFirstOrDefaultAsync<T>(string sql, object param = null, CommandType commandType = CommandType.Text)
    {
    return await _connection.QueryFirstOrDefaultAsync<T>(sql, param, _transaction, _commandTimeout, commandType);
    } public async Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, object param = null, string splitOn = "Id", CommandType commandType = CommandType.Text)
    {
    return await _connection.QueryAsync(sql, map, param, _transaction, true, splitOn, _commandTimeout, commandType);
    } #endregion Dapper Execute & Query public void Dispose()
    {
    if (IsTransactionStarted)
    Rollback(); _connection.Close();
    _connection.Dispose();
    _connection = null; DebugPrint("Connection closed and disposed.");
    } private void DebugPrint(string message)
    {
    #if DEBUG
    Debug.Print(">>> UnitOfWorkWithDapper - Thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, message);
    #endif
    }
    }
  • 定义UnitOfWork

    public interface IUnitOfWork : IDisposable
    {
    void SaveChanges();
    } public class UnitOfWork : IUnitOfWork
    {
    private readonly IContext _context; public UnitOfWork(IContext context)
    {
    _context = context;
    _context.BeginTransaction();
    } public void SaveChanges()
    {
    if (!_context.IsTransactionStarted)
    throw new InvalidOperationException("Transaction have already been commited or disposed."); _context.Commit();
    } public void Dispose()
    {
    if (_context.IsTransactionStarted)
    _context.Rollback();
    }
    }
  • 定义UnitOfWorkFactory

    public interface IUnitOfWorkFactory
    {
    IUnitOfWork Create();
    } public class DapperUnitOfWorkFactory : IUnitOfWorkFactory
    {
    private readonly DapperDBContext _context; public DapperUnitOfWorkFactory(DapperDBContext context)
    {
    _context = context;
    } public IUnitOfWork Create()
    {
    return new UnitOfWork(_context);
    }
    }
  • 定义服务扩展

    public class DapperDBContextOptions : IOptions<DapperDBContextOptions>
    {
    public string Configuration { get; set; } DapperDBContextOptions IOptions<DapperDBContextOptions>.Value
    {
    get { return this; }
    }
    } public static class DapperDBContextServiceCollectionExtensions
    {
    public static IServiceCollection AddDapperDBContext<T>(this IServiceCollection services, Action<DapperDBContextOptions> setupAction) where T : DapperDBContext
    {
    if (services == null)
    {
    throw new ArgumentNullException(nameof(services));
    } if (setupAction == null)
    {
    throw new ArgumentNullException(nameof(setupAction));
    } services.AddOptions();
    services.Configure(setupAction);
    services.AddScoped<DapperDBContext, T>();
    services.AddScoped<IUnitOfWorkFactory, DapperUnitOfWorkFactory>(); return services;
    }
    }
  • 怎么使用

    1. 创建一个自己的Context并继承DapperDBContext。下面测试的TestDBContext是采用MySQL数据库并返回MySqlConnection。

      public class TestDBContext : DapperDBContext
      {
      public TestDBContext(IOptions<DapperDBContextOptions> optionsAccessor) : base(optionsAccessor)
      {
      } protected override IDbConnection CreateConnection(string connectionString)
      {
      IDbConnection conn = new MySqlConnection(connectionString);
      return conn;
      }
      }
    2. 仓储类里面添加DapperDBContext引用

      public class UowProductRepository : IProductRepository
      {
      private readonly DapperDBContext _context;
      public UowProductRepository(DapperDBContext context)
      {
      _context = context;
      } public async Task<Product> GetByIDAsync(int id)
      {
      string sql = @"SELECT Id
      ,Name
      ,Quantity
      ,Price
      ,CategoryId
      FROM Product
      WHERE Id = @Id";
      return await _context.QueryFirstOrDefaultAsync<Product>(sql, new { Id = id });
      } public async Task<bool> AddAsync(Product prod)
      {
      string sql = @"INSERT INTO Product
      (Name
      ,Quantity
      ,Price
      ,CategoryId)
      VALUES
      (@Name
      ,@Quantity
      ,@Price
      ,@CategoryId)";
      return await _context.ExecuteAsync(sql, prod) > 0;
      }
      }
    3. Startup里面注册服务

      public void ConfigureServices(IServiceCollection services)
      {
      services.AddDapperDBContext<TestDBContext>(options => {
      options.Configuration = @"server=127.0.0.1;database=ormdemo;uid=root;pwd=password;SslMode=none;";
      }); services.AddTransient<IProductRepository, UowProductRepository>();
      services.AddTransient<ICategoryRepository, UowCategoryRepository>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
      }
    4. Controller调用

      public class ProductController : ControllerBase
      {
      private readonly IUnitOfWorkFactory _uowFactory;
      private readonly IProductRepository _productRepository;
      private readonly ICategoryRepository _categoryRepository; public ProductController(IUnitOfWorkFactory uowFactory, IProductRepository productRepository, ICategoryRepository categoryRepository)
      {
      _uowFactory = uowFactory;
      _productRepository = productRepository;
      _categoryRepository = categoryRepository;
      } [HttpGet("{id}")]
      public async Task<IActionResult> Get(int id)
      {
      var data = await _productRepository.GetByIDAsync(id);
      return Ok(data);
      } [HttpPost]
      public async Task<IActionResult> Post([FromBody] Product prod)
      {
      if (!ModelState.IsValid)
      {
      return BadRequest(ModelState);
      } //await _productRepository.AddAsync(prod); using (var uow = _uowFactory.Create())
      {
      await _productRepository.AddAsync(prod); uow.SaveChanges();
      } return NoContent();
      }
      }

源代码

Github

参考

ASP.NET Core 中的 ORM 之 Dapper的更多相关文章

  1. ASP.NET Core 中的 ORM 之 Entity Framework

    目录 EF Core 简介 使用 EF Core(Code First) EF Core 中的一些常用知识点 实体建模 实体关系 种子数据 并发管理 执行 SQL 语句和存储过程 延迟加载和预先加载 ...

  2. asp.net core 六 Oracle ORM

         .netcore 中 Oracle ORM      在真正将项目移植到.netcore下,才发现会有很多问题,例如访问Oracle,问题出现的时间在2017年底          参考连接 ...

  3. 如何在ASP.NET Core中编写高效的控制器

    ​通过遵循最佳实践,可以编写更好的控制器.所谓的"瘦"控制器(指代码更少.职责更少的控制器)更容易阅读和维护.而且,一旦你的控制器很瘦,可能就不需要对它们进行太多测试了.相反,你可 ...

  4. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  5. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  6. 在ASP.NET Core中使用百度在线编辑器UEditor

    在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...

  7. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  8. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  9. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

随机推荐

  1. 保存一份自己常用的packjson

    这里是一份专门针对react的插件配置, 有: es5的转换器,有ie的promise垫片,有蚂蚁金服的anth,还有用于消息通信的pubsub订阅发布系统,虽然现在不用了.... 用于发请求的axi ...

  2. idea打包含第三方依赖的jar包

    1.打开idea,打开java项目,选择file-->Project Structure,添加依赖的jar包 2.配置artfacts 点击ok,不需要做任何操作 点击jar,右键新建一个lib ...

  3. [转载] ul li css 做横向菜单

    原文地址: http://www.cnblogs.com/amylis_chen/archive/2011/09/24/2188398.html 第一步:建立一个无序列表 我们先建立一个无序列表,来建 ...

  4. eclipse中将一个项目作为library导入另一个项目中

    1. github上搜索viewpagerIndicator: https://github.com/JakeWharton/ViewPagerIndicator2. 下载zip包,解压,eclips ...

  5. MySQL终章

    视图 什么是视图 是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据 视图的特点 . 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系. . 视图是由基本表 ...

  6. 18. pt-pmp

    pt-pmp 是一个非常简单的工具,可以用来获取MySQL的堆栈信息.工具首先获取运行过程中的mysqld堆栈信息,然后将相似的线程进行汇总排序,根据调用频繁程度从高到低打印出来. 查看pt-pmp的 ...

  7. idea配置网络代理

    背景 公司限制连接外网,很多软件都被限制了,包括idea,只能通过代理上网. 使用代理上网,以往都是在IE的工具-Internet选项-连接里进行设置就OK了,谷歌浏览器啥的就可以上网了.但intel ...

  8. python_paramiko

    目录: paramiko模块介绍 paramiko模块安装 paramiko模块使用 一.paramiko模块介绍 paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件 ...

  9. linux关机、重启命令

    1.shutdown -h 10 //计算机将在10分钟后关机,且会显示在登录用户的当前屏幕中 2.shutdown -h now //立即关机 3.shutdown -h 20:25 //系统会在2 ...

  10. s6-2 UDP

    User Datagram Protocol  UDP 是一个无连接的(connectionless)的传输层协议  UDP传输数据段,无须建立连接  UDP 在 RFC 768中描述  很多 ...