2019年3月5日 By mikel 分类: 数据库

来源: SqlServer2008中事务使用的一些细节 – Hello World – CSDN博客

测试存储过程代码时候碰到了一个事务的细节问题,是在使用if else语句时候,报错begin tran和commit tran不配对,以前使用时候并没怎么留意这些小细节,所以出现了一些想当然的错误

存储过程如下:

Alter PROCEDURE [dbo].[proc_test]
@id int,
@result INT=-1 OUTPUT,
@msg AS varchar(50) OUTPUT
AS
BEGIN
BEGIN TRAN
BEGIN TRY
DECLARE @num INT=0
SELECT @num=num from temp_num where id=@id
IF (@num=0)
BEGIN
insert into temp_num values(floor(rand()*200)-100);–插入-100到100的随机数
SET @msg=’处理成功’
SET @result=1
END
ELSE
BEGIN
SET @msg=’处理失败’
SET @result=0
RAISERROR(@msg,16,1)
END
COMMIT TRAN
END TRY
BEGIN CATCH
SET @msg=ERROR_MESSAGE()
SET @result=0
ROLLBACK TRAN
END CATCH

RETURN @result
END

现在因为业务需求,增加了一个else if分支,调整后如下:
Alter PROCEDURE [dbo].[proc_test]
@id int,
@result INT=-1 OUTPUT,
@msg AS varchar(50) OUTPUT
AS
BEGIN
BEGIN TRAN
BEGIN TRY
DECLARE @num INT=0
SELECT @num=num from temp_num where id=@id
IF (@num=0)
BEGIN
insert into temp_num values(floor(rand()*200)-100);–插入-100到100的随机数
SET @msg=’处理成功’
SET @result=1
END
ELSE IF(@num<0)
BEGIN
update temp_num set num=-1*num where id=@id;–将负数变正
ROLLBACK TRAN
END
ELSE
BEGIN
SET @msg=’处理失败’
SET @result=0
RAISERROR(@msg,16,1)
END
COMMIT TRAN
END TRY
BEGIN CATCH
SET @msg=ERROR_MESSAGE()
SET @result=0
ROLLBACK TRAN
END CATCH

RETURN @result
END
那么问题来了,该存储过程执行到新增的else if分支就直接报错了“ROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION。”

ELSE IF(@num<0)
BEGIN
update temp_num set num=-1*num where id=@id;–将负数变正
ROLLBACK TRAN
END
写c#代码时候

public int TestMethod()

{

if(a>0)

{

a=a+1;

}

else if(a<0)

{

return 0;

}

else

{

a=a-1;

}

return 1;

}

c#中这么写,没毛病,编译器也不会报错,但是想当然的把begin tran、commit tran/rollback tran当成return这样的用就有问题了,sqlserver语法检查通不过!

begin tran 和 commit tran、rollback tran的配对,在碰到if else时候,如果你在分支里写了commit tran、rollback tran,那么每个分支都需要提交或者回滚,不能部分写分支里,部分写if else语句结束之后

所以调整后的存储过程

Alter PROCEDURE [dbo].[proc_test]
@id int,
@result INT=-1 OUTPUT,
@msg AS varchar(50) OUTPUT
AS
BEGIN
BEGIN TRAN
BEGIN TRY
DECLARE @num INT=0
SELECT @num=num from temp_num where id=@id
IF (@num=0)
BEGIN
insert into temp_num values(floor(rand()*200)-100);–插入-100到100的随机数
SET @msg=’处理成功’
SET @result=1
COMMIT TRAN
END
ELSE IF(@num<0)
BEGIN
update temp_num set num=-1*num where id=@id;–将负数变正
COMMIT TRAN
END
ELSE
BEGIN
ROLLBACK TRAN
SET @msg=’处理失败’
SET @result=0
RAISERROR(@msg,16,1)
END

END TRY
BEGIN CATCH
SET @msg=ERROR_MESSAGE()
SET @result=0
ROLLBACK TRAN
END CATCH

RETURN @result
END

也就是说,如果你在分支里使用了commit、rollback,那么每个分支里都必须提交或者回滚,并且if else语句之后不能再次提交或者回滚。这样写起来比较麻烦,其实最好的做法是提前定义一个变量,if else中对变量赋值,结尾判断值再进行提交或者回滚操作。
此外,begin tran写在begin if之内或者之外都不影响catch语句中的回滚

———————
作者:数据的流
来源:CSDN
原文:https://blog.csdn.net/shujudeliu/article/details/78783613
版权声明:本文为博主原创文章,转载请附上博文链接!

SqlServer2008中事务使用的一些细节 – Hello World – CSDN博客已关闭评论
2019年2月27日 By mikel 分类: JavaScript

来源: 微信分享网页链接自定义图片和文字描述 – 走召爱木土的博客 – CSDN博客

今天开发需要微信分享网页链接自定义图片和文字描述,于是网上各种查找资料和各种看手册,遇到了好多坑,不过啃了半天以后终于把问题解决了,以防以后忘记,今天记录一下;
首先,由于微信已经发布了想要分享链接必须调用认证了的公众号的JSSDK接口,所以,像以前的在html页面中的head中放入图片,我试过已经不管用了,当然不是绝对的,但是我这个方法试了多好次,不能用,所以没有办法只好调接口来做这个功能了;
废话不多说,
首先第准备工作:
需要有一个认证了的公众号;

然后开始了我们的代码操作:
一: 在html中引入js文件
<script type=”text/javascript” src=”http://res.wx.qq.com/open/js/jweixin-1.2.0.js”></script>

这里写图片描述

二: 在控制器中假如一下代码,引入jssdk.php文件,我放在extend文件夹下面,
这个不是强制要求,大家随意,只要文件引入正确
//获取apptoken
        include EXTEND_PATH . "\jssdk\jssdk.php";
        $jssdk = new \JSSDK('你的appid','你的APPSecret');//这里填写自己的appid 和secret
        $signPackage = $jssdk->GetSignPackage();

三: 回到html中,将发送来的数据放在head中;这个好处就是,数据不需要写死,以防以后出现问题;
<script>
		wx.config({
            debug: false,
            appId: '{$signPackage["appId"]}',
            timestamp: '{$signPackage["timestamp"]}',
            nonceStr: '{$signPackage["nonceStr"]}',
            signature: '{$signPackage["signature"]}',
            jsApiList: [
	            //我只调用了两个分享接口,分别是朋友圈和个人,大家有其它需要可以去文档中查找接口
				'onMenuShareTimeline',
				'onMenuShareAppMessage'
			]
		});
		wx.ready(function () {
			var shareData = {
				title: '标题',	//	标题
				desc: '描述',	//	描述
				link: '链接',	//	分享的URL,必须和当前打开的网页的URL是一样的
				imgUrl: '缩略图完整路径'	//	缩略图地址
			};
			wx.onMenuShareAppMessage(shareData);
			wx.onMenuShareTimeline(shareData);
		});
		wx.error(function (res) {
			//alert(res.errMsg);//错误提示
		});
	 </script>

这里写图片描述

四: 将文件夹放入到你的项目中,也可以和第二步一起进行,在其中测试错误;


五:一定要在公众号里设置IP的白名单,否则一直报错,说你没有权限可以拿到token!


好了,大概就是这样,按流程走完,就可以分享网页链接的时候带上你自定义的图片和内容描述了
微信分享网页链接自定义图片和文字描述 – 走召爱木土的博客 – CSDN博客已关闭评论
2019年2月27日 By mikel 分类: 开发笔记

来源: 基于MUI的电影新闻的webapp项目开发 – luoshao2000的博客 – CSDN博客

写在前面:之前,本人在自学webapp的过程中,一直没有找到一份比较完整的开发步骤文档,都是一些零零散散的文档,走了很多弯路,也耽误了很多的时间,其中尝试了多种框架,感觉MUI这种H5+的模式是比较适合的一种WEBAPP开发模式,开发难度稍高于纯H5,但应用流畅度接近原生APP(本人和dcloud没有一毛钱关系),是值得推荐的一种混合型APP开发模式。为了让广大WEBAPP初学者少走弯路,大家可以跟着本项目文档走下来,基本上就掌握了WEBAPP开发的很多方面。本项目不涉及服务端,服务端实现较为简单,可以使用任意的语言实现,只需要能根据url返回json数据即可,所以本项目直接使用了网上公开的数据API。

1    项目简介
项目功能为加载知乎日报和豆瓣电影信息,可以查看新闻、影评和观看预告片。
2    项目资源
https://www.jianshu.com/p/42630373e1bc
2.1    知乎日报API
2.1.1    最新新闻列表:https://news-at.zhihu.com/api/4/news/latest
2.1.2    某条新闻内容:https://news-at.zhihu.com/api/4/news/3892357
2.2    豆瓣电影API
2.2.1    在映电影列表:https://douban.uieee.com/v2/movie/in_theaters?city=福州
2.2.2    某部电影信息:https://douban.uieee.com/v2/movie/subject/26985127
2.3    Json格式工具
打开http://www.bejson.com/,把获得的json字符串直接粘贴到输入框,然后验证
2.4    HTML模板工具
http://www.jq22.com/jquery-info1097
JS资源下载
打开https://github.com/aui/art-template/tree/master/lib ,下载template-web.js

3    开发工具
3.1    HBuilder
http://download.dcloud.net.cn/HBuilder.9.1.14.windows.zip
3.2    夜神安卓模拟器
https://res06.bignox.com/full/20180816/b78465a3b8a9457eb47df54e477a1a60.exe?filename=nox_setup_v6.2.2.3_full.exe

4    开发过程
4.1    项目创建
使用Hbuilder新建移动APP项目,把template-web.js拷贝到js目录下; 新建subpages子目录,以后的页面都是放在该目录下。
4.2    入口页开发
打开index.html,写上一个页头mHeader和一个页脚导航mTab,修改链接和名称。

效果如下:

在subpages目录下,新建对应的四个页面,先写上简单的文字标识,后面会进行功能完善。

采用webView的方式来进行Tab切换,代码有点多,可以拷贝官方文档,进行局部修改,其实只要修改subpages即可,主要要和mTab中的设置要一致,否则会报告错误,因为名字错了,就无法找到文件资源,也就无法初始化了。

※初始化代码要写在plusReady事件中。
4.3    首页开发
暂时先留空,因为这个页面的内容是其他模块信息的综合而已,先做其他页面,在来组装本页的内容
4.4    新闻列表
打开newslist.html,新建一个mbody,
引入<script src=”../js/template-web.js” type=”text/javascript” charset=”utf-8″></script>
在mui.plusReady中编写ajax,获取数据

新建一个mListMedia块,删除多余的li,留下一个,用于制作模板(具体做法请参考art-template),最后模板如下:

※注意此图与上图的对应关系,script的id=“newlistScript”与template函数的参数名“newlistScript”是对应的。Mui(“#newlist”)是放置当前模板内容的父元素id,要记得给mbody的div加上id=‘newlist’。
※在这个过程当中,可以先用浏览器查询下数据,把数据放入www.bejson.com中进行观察,来指导编写代码。
绑定新闻条目的点击事件:

※解释:off是为了先把以前绑定的事件解除(一般不做也没有关系),on绑定tap点击事件到当前元素下的所有li元素上;this.getAttribute是获得li上的id属性值;openWindow是当点击某个li后,打开下一个网页,extras是传参;
页面效果如下:

4.5    新闻详情页
新建一个mHeader,取名为新闻详情,并带有返回键<
创建一个mBody,取id为news
引入template-web.js
创建mui.plusReady事件,编写代码:

创建一个卡片视图,(奇怪,hbuilder没有卡片的自动生成快捷键?),删除多余的div,留下一个做为模板用,模板最后如下:

页面效果如下:

4.6    豆瓣电影
打开movielist.html,
创建一个mbody
引入template-web.js
创建mui.plusReady事件,并编写代码

创建自定义模板

绑定tap事件

5    电影详情页
创建movie.html,
创建mHeader,创建mbody,取id为movie
创建卡片布局(见官网)
创建mui.plusReady事件,并编写代码

创建模板
把影片图片放在卡片的头部,把影片信息,预告片信息,影评信息分别放入卡片布局的内容区,具体代码见源代码。

※由于横向滚动条的预告片部分是动态生成的,所以要让它有滚动效果,必须重新初始化

6    首页开发
6.1    头部滚动条
滚动条为当前评分较高的电影海报,
在mui.plusReady中获取电影列表

自定义排序比较函数:降序排序

模板生成

6.2    下部列表
在mui.plusReady中拉数据

生成模板

7    项目效果预览

首页:

新闻列表

豆瓣电影

新闻详情页:

电影详情页:

预告片播放:

8. 项目源代码:

https://download.csdn.net/download/luoshao2000/10618471
———————
作者:包包老师
来源:CSDN
原文:https://blog.csdn.net/luoshao2000/article/details/81914525
版权声明:本文为博主原创文章,转载请附上博文链接!

基于MUI的电影新闻的webapp项目开发 – luoshao2000的博客 – CSDN博客已关闭评论
2019年2月26日 By mikel 分类: PHP

来源: html5+JS+PHP 预览并异步上传图片的功能 – 转身_错过 – CSDN博客

Html部分

<div class=”from-group clearfix from-group-padding”>
<label class=”col-sm-1 label-right”>微缩图 :</label>
<div class=”col-sm-2″>
<a href=”javascript:;” id=”uploadimg”>
<img src=”/images/default-thumbnail.png” width=”180″ style=”” id=”imgpre”>
<input type=”file” id=”imgFile” onchange=”imgPreview(this);return false;”/>
<input type=”hidden” name=”course_pic” value=”” id=”getpic”>
</a>
</div>
<div class=”input-note”>尺寸:640px × 363px</div>
</div>

CSS部分

/* 图片上传CSS */
#uploadimg{display:block; width:180px; height:180px;position:relative; overflow:hidden;}
#imgFile{position:absolute; right:0; top:0; font-size:100px; opacity:0; filter:alpha(opacity=0);cursor:pointer}
js部分
function imgPreview(fileDom){

//判断是否支持FileReader
if (window.FileReader) {
var reader = new FileReader();
} else {
toastr.error(‘不支持FileReader API 请升级您的设备’);
}
var file = fileDom.files[0];
var imageType = /^image\//;
//是否是图片
if (!imageType.test(file.type)) {
toastr.error(‘请选择图片!’);
return;
}
//读取完成
reader.onload = function(e) {
// //获取图片展示的dom
// var img = document.getElementById(“imgpre”);
// // 图片路径设置为读取的图片
// img.src = e.target.result;
// ajax 上传图片
$.post(“/Course/uploadimg”, {course_img: e.target.result}, function(ret) {
if (ret.img!=”) {
toastr.success(‘图片上传成功!’);
$(‘#imgpre’).attr(‘src’,’/’+ret.img);
$(‘#getpic’).attr(‘value’,’/’+ret.img);
alert(ret.img);
// $(‘#showimg’).html(‘<img src=”‘ + ret.img + ‘”>’);
// 返回给前台 图片地址 放到隐藏框中
} else {
toastr.error(‘图片上传错误!’);
}
},’json’);
};
reader.readAsDataURL(file);
}//imgPreview结束
php部分

public function uploadimg(){
$pic = Request::param();
//获取图片信息
list($type,$file) = explode(‘,’,$pic[‘course_img’]);
// 判断类型
if(strstr($type,’image/jpeg’)!=”){
$ext = ‘.jpg’;
}elseif(strstr($type,’image/gif’)!=”){
$ext = ‘.gif’;
}elseif(strstr($type,’image/png’)!=”){
$ext = ‘.png’;
}
// 生成的文件名
$photo = md5(time()).$ext;
$file_dir = ‘uploads/images/’.Date(‘Ymd’);
//判断文件夹是否存在
if (!is_dir($file_dir)) {
mkdir($file_dir,755,true);
}
if(file_put_contents($file_dir.’/’.$photo,base64_decode($file), true)){
$ret = [‘img’=>$file_dir.’/’.$photo];
//这里必须用echo返回json 用return jquery接收不到
echo json_encode($ret);
}
}

———————
作者:转身_错过
来源:CSDN
原文:https://blog.csdn.net/qq_41321149/article/details/81293872
版权声明:本文为博主原创文章,转载请附上博文链接!

html5+JS+PHP 预览并异步上传图片的功能 – 转身_错过 – CSDN博客已关闭评论
2019年2月20日 By mikel 分类: 架构设计

1 主流深度学习框架对比 当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层。比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android

来源: Tensorflow源码解析1 — 内核架构和源码结构 – 阿里云云栖社区 – 博客园

1 主流深度学习框架对比

当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层。比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android Framework。深度学习也不例外,框架层为上层模型开发提供了强大的多语言接口、稳定的运行时、高效的算子,以及完备的通信层和设备层管理层。因此,各大公司早早的就开始了深度学习框架的研发,以便能占领市场。当前的框架有数十种之多,主流的如下(截止到2018年11月)

显然TensorFlow是独一无二的王者。第二名Keras,它是对TensorFlow或Theano接口的二次封装,严格意义上并不是一个独立的深度学习框架。TensorFlow目前也已经集成了Keras,使得安装了TensorFlow的用户就可以直接使用Keras了。

TensorFlow之所以能够从数十种框架中脱颖而出,主要优点有

  1. 出身高贵,是谷歌出品的。但其他很多框架出身也不差,例如PyTorch之于Facebook,MXNET之于Amazon
  2. 2015年就开源了,比较早的俘获了一大批开发者。这个确实是tf的一大先发优势,但PyTorch的前身Caffe,以及MXNET开源时间都不晚,而且Caffe流行时间比tf早,后来才被赶超的。更有Theano这样的绝对老前辈。由此可见,软件开源是多么重要。目前流行的深度学习框架也基本都开源了。
  3. 支持的开发语言多,支持Python Java Go C++等多种流行语言。相比某些框架,确实是优势很大。相比MXNET则小巫见大巫了。MXNET早期发展的一个主要方向就是前端多语言的支持,连MATLAB R Julia等语言都支持了。
  4. 运行效率高。早期的时候,其实tf的运行效率比很多框架都要低一些的。
  5. 安装容易,用户上手快,文档齐全,社区活跃。这个是tf的一个较大优势,特别是社区方面,也就是我们常说的生态优势。互联网头部集中效应十分明显,体现在开源软件上也是一样。这也是我认为最大的一个优势。

总结起来,TensorFlow虽然每个方面都不是绝对领先的优势,但贵在每个方面都做的不错,因此最终能够一骑绝尘,独领风骚。

学习Tensorflow框架内核,可以理解前端接口语言的支持,session生命周期,graph的构建、分裂和执行,operation的注册和运行,模块间数据通信,本地运行和分布式运行模式,以及CPU GPU TPU等异构设备的封装支持等。学习这些,对于模型的压缩 加速 优化等都是大有裨益的。

2 TensorFlow系统架构

TensorFlow设计十分精巧,基于分层和模块化的设计思想进行开发的。框架如下图

整个框架以C API为界,分为前端和后端两大部分。

  1. 前端:提供编程模型,多语言的接口支持,比如Python Java C++等。通过C API建立前后端的连接,后面详细讲解。
  2. 后端:提供运行环境,完成计算图的执行。进一步分为4层
    1. 运行时:分为分布式运行时和本地运行时,负责计算图的接收,构造,编排等。
    2. 计算层:提供各op算子的内核实现,例如conv2d, relu等
    3. 通信层:实现组件间数据通信,基于GRPC和RDMA两种通信方式
    4. 设备层:提供多种异构设备的支持,如CPU GPU TPU FPGA等

模型构造和执行流程

TensorFlow的一大特点是,图的构造和执行相分离。用户添加完算子,构建好整图后,才开始进行训练和执行,也就是图的执行。大体流程如下

  1. 图构建:用户在client中基于TensorFlow的多语言编程接口,添加算子,完成计算图的构造。
  2. 图传递:client开启session,通过它建立和master之间的连接。执行session.run()时,将构造好的graph序列化为graphDef后,以protobuf的格式传递给master。
  3. 图剪枝:master根据session.run()传递的fetches和feeds列表,反向遍历全图full graph,实施剪枝,得到最小依赖子图
  4. 图分裂:master将最小子图分裂为多个Graph Partition,并注册到多个worker上。一个worker对应一个Graph Partition。
  5. 图二次分裂:worker根据当前可用硬件资源,如CPU GPU,将Graph Partition按照op算子设备约束规范(例如tf.device(‘/cpu:0’),二次分裂到不同设备上。每个计算设备对应一个Graph Partition。
  6. 图运行:对于每一个计算设备,worker依照op在kernel中的实现,完成op的运算。设备间数据通信可以使用send/recv节点,而worker间通信,则使用GRPC或RDMA协议。

3 前端多语言实现 – swig包装器

TensorFlow提供了很多种语言的前端接口,使得用户可以通过多种语言来完成模型的训练和推断。其中Python支持得最好。这也是TensorFlow之所以受欢迎的一大原因。前端多语言是怎么实现的呢?这要归功于swig包装器。

swig是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。在TensorFlow使用bazel编译时,swig会生成两个wrapper文件

  1. pywrap_tensorflow_internal.py:对接上层Python调用
  2. pywrap_tensorflow_internal.cc:对接底层C API调用。

pywrap_tensorflow_internal.py 模块被导入时,会加载_pywrap_tensorflow_internal.so动态链接库,它里面包含了所有运行时接口的符号。而pywrap_tensorflow_internal.cc中,则注册了一个函数符号表,实现Python接口和C接口的映射。运行时,就可以通过映射表,找到Python接口在C层的实现了。

4 tensorflow 源码结构

TensorFlow源码基本也是按照框架分层来组织文件的。如下

其中core为tf的核心,它的源码结构如下

5 总结

TensorFlow框架设计精巧,代码量也很大,我们可以从以下部分逐步学习

    1. TensorFlow内核架构和源码结构。先从全局上对框架进行理解。
    2. 前后端连接的桥梁–Session,重点理解session的生命周期,并通过相关源码可以加深理解Python前端如何调用底层C实现。
    3. TensorFlow核心对象—Graph。图graph是TensorFlow最核心的对象,基本都是围绕着它来进行的。graph的节点为算子operation,边为数据tensor。
    4. TensorFlow图的节点 — Operation。operation是图graph的节点,承载了计算算子。
    5. TensorFlow图的边 — Tensor。Tensor是图graph的边,承载了计算的数据。
    6. TensorFlow本地运行时。
    7. TensorFlow分布式运行时。和本地运行时有一些共用的接口,但区别也很大。
    8. TensorFlow设备层。主要了解设备层的定义规范,以及实现。
    9. TensorFlow队列和并行运算。
    10. TensorFlow断点检查checkpoint,模型保存Saver,以及可视化tensorboard。这三个为TensorFlow主要的工具。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

Tensorflow源码解析1 — 内核架构和源码结构 – 阿里云云栖社区 – 博客园已关闭评论
2019年2月20日 By mikel 分类: 架构设计

现代管理教育对供应链的定义为“供应链是围绕核心企业,通过对商流,信息流,物流,资金流的控制,从采购原材料开始,制成中间产品以及最终产品,最后由销售网络把产品送到消费者手中的将供应商,制造商,分销商,零

来源: 供应链金融&区块链应用 – 莱布尼茨 – 博客园

现代管理教育对供应链的定义为“供应链是围绕核心企业,通过对商流,信息流,物流,资金流的控制,从采购原材料开始,制成中间产品以及最终产品,最后由销售网络把产品送到消费者手中的将供应商,制造商,分销商,零售商,直到最终用户连成一个整体的功能网链结构。那什么是核心企业呢?

当供应链中某一企业在整个供应链中占据主导地位,对其他成员具有很强的辐射能力和吸引能力,通常称该企业为核心企业或主导企业。核心企业是供应链的物流中心、信息中心和资金周转中心。在供应链竞争中,核心企业承担供应链组织者和管理者的职能。 核心企业的关键在技术,而在技术更高一层的是管理,例如精益管理的鼻祖丰田汽车,它就是以自身的生产为核心,提供定单,围绕这个企业,形成了一二三个批次的供应链条,成百上千个中小企业为之服务。


供应链金融

在传统供应链金融业务模式下,业务主体包括供应商(上游企业)、经销商(下游企业)、核心企业、银行、仓储机构以及物流公司等,业务模式主要包括三种,分别为应收类(应收账款融资模式)、预付类(保兑仓融资模式)以及存货类(融通仓融资模式)(可参看 传统供应链金融业务模式:应收账款融资、保兑仓融融资、融通仓融资)。其中应收账款融资与保理业务关系密切。

保理

全称保付代理,又称托收保付,卖方将其现在或将来的基于其与买方订立的货物销售/服务合同所产生的应收账款转让给保理商(提供保理服务的金融机构),由保理商向其提供资金融通、买方资信评估、销售账户管理、信用风险担保、账款催收等一系列服务的综合金融服务方式。

国际上对保理的定义五花八门,我们只要掌握精髓就好。

由来:保理业务是从出口代理交易方式演变而来的,起源于14世纪英国毛纺工业。当时英国毛纺织品是在寄售基础上委托专业代理商代销的。这些代理商向国外买主出售商品,同时向出口商担保买主的商业信用。当时由于交通不便,外贸业务往来活动比较缓慢。如果在国外没有可靠的代理人进行协助,任何出口企业很难取得成功。到18世纪,美国的一些代理商逐步以其高度效率和雄厚资金掌握了为扩大其国内市场所需要的代贷管理工作。他们的地位也逐步由以前被委托的代理人身分演变为独立的经济实体——保理商。保理商根据保理合同专门为有关商业企业提供信贷和信用管理服务。经过不断地发展,现代保理商已能提供一揽子服务,包括向卖方提供买方资信调查,100%货款商业风险担保,应收账款管理和资金融通等。

盈利模式:保理业务的盈利模式一般为向客户收取利息及保理费,不仅能带来丰厚的利润,更为重要的是可为保理公司创造可观的中间业务收入。一般来说,销售方保理商除了可以获得发票金额一定比例的佣金外,还可以通过向销售商提供融资服务获得融资利息;而作为购买方保理商,由于承担买方信用,收取的佣金比例更高。

坏账担保(full protection against bad debts)保理商为自己核准的应收账款提供100%的担保,有效消除因买方信用给出口方造成的坏账风险的担保服务。

扩展阅读:五分钟教你看懂供应链金融(文尾抛出的问题可看读者评论)

融资租赁

融资租赁和供应链金融是不同概念,前者是一种融资形式,它可以融入到供应链金融的保兑仓融资融通仓融资这两种模式中,当然它是独立于具体金融应用领域的。

融资租赁分为直租和售后回租两种模式。直租类似于分期付款,可以降低客户购买设备的门槛,但在企业角度看,它规避了分期付款的缺点,可以使企业实现一次性回款,减少了企业的应收账款。售后回租也类似于分期付款,只不过商品原本是承租人自己的,转卖给融资租赁公司,融资租赁公司再租售给承租人而已,绕这么一大弯,承租人手里的可用资金却多了。

保兑仓&融通仓

要了解两个概念仓单质押银行承兑汇票

仓单质押

仓单:是指仓储公司签发给存储人或货物所有权人的记载仓储货物所有权的唯一合法的物权凭证,仓单持有人随时可以凭仓单直接向仓储方提取仓储货物。仓单质押指银行与借款人(出质人)、保管人(仓储公司)签订合作协议,以保管人签发的借款人自有或第三方持有的存货仓单作为质押物向借款人办理贷款的信贷业务。

扩展阅读:贷款按照有无担保一般分为信用贷款和担保贷款,其中担保贷款又分为保证贷款、抵押贷款和质押贷款。一般来说,银行认可的抵押物主要是不动产如房屋、厂房、机器设备等,质押物主要是银行存单、国债等有价证券。尽管生产企业或商业企业的存货也具有一定的价值,理论上也可以进行抵押,但是由于银行难以对存货进行有效的监管,同时缺乏对存货市场价值的评估,一般银行不愿意接受存货抵押借款的方式。这样,对于那些缺乏合适抵押品的企业,尽管其拥有大量的存货,却难以从银行获得贷款支持。大多数中小企业都存在这种尴尬的局面。仓单融资实质是一种存货抵押融资方式,通过银行、仓储公司和企业的三方协议,引入专仓储公司在融资过程中发挥监督保管抵押物、对抵押物进行价值评估、担保等作用,实现以企业存货仓单为抵押的融资方式。仓单融资适用于流通性较高的大宗货物,特别是具有一定国际市场规模的初级产品,如有金属及原料、黑色金属及原料、煤炭、焦碳、橡胶、纸浆以及大豆、玉米等农产品。任何特制的商品、专业机械设备、纺织服装,家电等产品,一般难以取得银行仓单融资的机会(这就给了其它融资机构提供服务的机会)。

银行承兑汇票

这是一个银行、供应方、采购方三方共赢的商业模式,可参看 张虎成讲票据(三)终于有人把银行承兑汇票彻底讲清楚了。目下很多平台也提供票据结算业务,比如找钢网,应该是与企业低贴息结算(相对银行贴息率较低),然后等着票据到期去银行取钱,赚这一部分贴息率。

保兑仓:企业分批赎货。融通仓:融资企业拿这批货抵押贷款,核心企业提供担保和[可能的]回购。

传统供应链金融存在的问题

  1. 由于银行依赖核心企业信用,出于风控的考虑,银行仅愿意对核心企业有直接应付账款义务的上游供应商(即一级供应商)提供保理业务,或对其一级经销商提供预付款或者存货融资。这就导致了有巨大融资需求的二级、三级等供应商/经销商的资金需求得不到满足,无法充分挖掘整个供应链的潜力。
    资金来自于银行等金融机构,银行在放款上具有强有力的话语权,企业在向银行提出融资申请后,按照它自己的标准来对企业进行评估,看它是否具有偿还能力。例如,有些中小企业虽然基于真实的交易背景具有偿还能力,可是并没能从账面财务信息表达,特别是当这些企业没有有效的、可供抵押的固定价值资产时,银行只能拒绝给企业融资。在这种情况下,中小企业只能以更高的价格,转向其他中小金融机构(如保理公司、民间借贷等)进行融资。如何将真实的交易背景层层穿透至供应链的末端,成为了最大的难题。
  2. 由于牵涉到多方以及多环节,各方须签署复杂的纸质合同,另外还涉及到合同的不同版本,因此维护和管理难度较大。在办理业务时,常需要找到特定版本的原始文档,及指定专人前来签署(如在实际金融操作中,银行非常关注应收账款债权“转让通知”的法律效应,如果核心企业无法签回,银行不会愿意授信。据了解,银行对于签署这个债权“转让通知”的法律效应很谨慎,甚至要求核心企业的法人代表去银行当面签署)。
  3. 信息不对称、不透明,金融方需要花费人力物力去鉴别交易真伪和核实线下抵押品,这反过来提高了融资方的融资成本。

国内市场前景

国家统计局数据显示,2016年末,我国规模以上工业企业应收账款12.6万亿元,同比增长10% ,这其中产生了企业巨大的融资需求。而相比于巨大的应收账款,2015年我国年商业保理量仅在2000亿元左右,可以看出,还有大量供应链需求没有被满足,因而供应链金融行业发展空间巨大。网贷天眼发布的《2016互联网+供应链金融研究报告》,预测2020年我国供应链金融市场规模将达到15万亿左右,这是一个非常巨大的市场。


区块链应用

笔者认为,虽然区块链脱胎于数字货币这种纯虚拟产物,但供应链金融反而是更能培养她成长的合适土壤。这是因为首先,供应链金融这个场景具有万亿级别的市场规模,天花板足够高;其次,这个场景天然需要多方合作,却又没有一个传统中心化的机构在治理,需要用区块链来建立信任;同时,在技术上这个场景并不需要高并发,目前的区块链技术能够满足。

与业务相关的核心功能就是基于真实共享的上链交易数据自动产生数字票据,该票据可以在公开透明、多方见证的情况下进行随意的拆分、汇总和转移。相当于把整个供应链中的信用变得可传导、可追溯,为大量原本无法融资的中小企业提供了融资机会,极大地提高票据的流转效率和灵活性,降低中小企业的资金成本。

如何将实体资产映射为数字资产,并实时同步状态,是个较为麻烦的事情。以目前的技术来说,通过RFID、NFC等射频方案可自动同步信息,然而资产损耗(如丢失、芯片故障)等场外因素仍需要手动盘点。

如何切入

如何切入是个难点,特别是涉及到多方合作的项目,可以从核心企业的影响力强制要求上下游加入 or 提供一个让人无法拒绝的服务:)

  • 联盟链模式——直接与核心企业/平台合作,为其提供区块链底层解决方案,在积累足够多数据之后,通过搭建联盟链,对接资金方提供金融服务。
  • 私有链模式——从提供供应链管理服务入手,比如溯源、追踪、可视化等,将信息流、物流和资金流整合到一起,在此基础之上从事金融服务。

大致可分为以下几步:

  1. 数据上链,将交易数据放到链上,利用区块链的特性使其不可篡改,并提供数据的确权,溯源等服务。
  2. 资产数字化,把仓单、合同、以及可代表融资需求的区块链票据都变成数字资产,且具有唯一、不可篡改、不可复制等特点。
  3. 数字资产的交易,供应链金融平台将转变成一个金融资产交易所,将非标的企业贷款需求转变成标准化的金融产品,进行代币化,对接投融资需求,进行价值交易。

最终,区块链技术将能有效地增强供应链金融资产的流动性,调动新型的融资工具和风控体系帮助覆盖中小企业融资的长尾市场,催生供应链金融即服务。

作用

提高行业透明度:区块链为供应链提供了交易状态实时、可靠的视图,有效提升了交易透明度,这将大大方便中介机构基于常用的发票、库存资产等金融工具进行放款。其中抵押资产的价值将根据现实时间实时更新,最终这将有助于建立一个更可靠和稳定的供应链金融生态系统。

降低金融成本:同样的,由于区块链填补了信任鸿沟,并能实时查阅包括合同条款在内的所有数据,另外还有智能合约的加持,减少了人工核实和反馈的成本,这部分同样会反映到金融服务上。

新的商业模式:新型供应链金融平台,主要的参与者包括平台本身、保理机构、中介金融机构、企业、个人甚至是算法公司。平台提供数据,算法公司可以基于平台提供的API接口,开发金融模型,并出售给第三方金融机构和保理公司。

提升用户体验:由于用户数据(包括交易数据、征信、资产配置等)都已上链(敏感数据可配置为只有特定机构可查询),平台可推送合适的金融方案给到用户,用户选择后资方会自动划拨款项到用户银行账户,而不需要漫长的资料准备、各种复杂的条款、审批等等。

ps:并不是说区块链上的数据都一定是真实的,但至少比传统系统如ERP之类的方便排查的多,且更易于发现。


其它

敞口:一般指的是风险敞口。指在金融活动中存在金融风险的部分以及受金融风险影响的程度。

托盘:钢贸行业的仓单质押,属于保兑仓。

外贸

T/T: 电汇,也就是说客户直接从他的开户银行把钱付到你的开户银行中,或者反之。前T/T就是预先付款,后T/T就是先发货后付款。前T/T当然就对卖家有保障对买家不利了。
L/C是指信用证。一般都要求买家开不可撤销信用证。意思是买家把钱存在银行,然后委托银行按照一定的外贸流程,预先设定好受益人,交易方式,所需单据等要求,卖方根据信用证要求出货并把单据寄到对方银行,单据都没错银行就直接给你放款,不受买家的要求影响。对卖方买方都有保障。对单据要求比较高,而且手续费高。

长尾

长尾效应,英文名称Long Tail Effect。“头”(head)和“尾”(tail)是两个统计学名词。正态曲线中间的突起部分叫“头”;两边相对平缓的部分叫“尾”。从人们需求的角度来看,大多数的需求会集中在头部,而这部分我们可以称之为流行,而分布在尾部的需求是个性化的,零散的小量的需求。而这部分差异化的、少量的需求会在需求曲线上面形成一条长长的“尾巴”,而所谓长尾效应就在于它的数量上,将所有非流行的市场累加起来就会形成一个比流行市场还大的市场。

 

参考资料:

供应链金融三类模式的最全对比分析

研究报告:区块链+供应链金融

 

转载请注明本文出处:https://www.cnblogs.com/newton/p/9827715.html

供应链金融&区块链应用 – 莱布尼茨 – 博客园已关闭评论
2019年2月20日 By mikel 分类: ASP.NET, 架构设计

Docker可以说是现在微服务,DevOps的基础,咱们.Net Core自然也得上Docker。.Net Core发布到Docker容器的教程网上也有不少,但是今天还是想来写一写。 你搜.Net c

来源: .Net Core in Docker – 在容器内编译发布并运行 – Agile.Zhou – 博客园

Docker可以说是现在微服务,DevOps的基础,咱们.Net Core自然也得上Docker。.Net Core发布到Docker容器的教程网上也有不少,但是今天还是想来写一写。
你搜.Net core程序发布到Docker网上一般常见的有两种方案:

  • 1、在本地编译成Dll文件后通过SCP命令或者WinSCP等工具上传到服务器上,然后构建Docker镜像再运行容器。该方案跟传统的发布很像,麻烦的地方是每次都要打开相关工具往服务器上复制文件。
  • 2、在服务端直接通过Git获取最新源代码后编译成Dll然后构建Docker镜像再运行容器。该方案免去了往服务器复制文件这步操作,但是服务器环境需要安装.Net Core SDK 来编译源代码。
    自从用了Docker简直懒的不能自理,我既不想手工复制文件到服务器,也不想在服务器装.Net Core环境。显然只要Docker镜像包含.Net Core SDK环境就可以在Docker内帮我们编译代码然后运行,这样连我们的服务器都不用装啥.Net Core的环境拉。

    在Docker内编译发布.Net Core程序并运行

    新建一个Asp.net Core MVC项目

    我们使用一个Asp.net Core MVC程序来演示如何发布到Docker并运行。
    新建项目
    使用vs新建一个Asp.net core mvc项目

  public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return Content($"Core for docker , {DateTime.Now} , verson 2");
        }
    }

修改HomeController下的index Action,直接输出一段文字

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .UseKestrel(op =>
            {
                op.ListenAnyIP(5000);
            })
            .UseStartup<Startup>();

修改Program下的CreateWebHostBuilder方法,让Kestrel监听5000端口


本地运行一下试试

推送源码到代码仓库

把我们的代码推送到对应的Git仓库,方便我们从部署服务器上直接拉取最新的代码。

X:\workspace\CoreForDocker>git remote add origin https://gitee.com/kklldog/CoreForDocker.git

X:\workspace\CoreForDocker>git push -u origin master
Username for 'https://gitee.com': xxx@gmail.com
Password for 'https://xxx@gmail.com@gitee.com':
Counting objects: 88, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (83/83), done.
Writing objects: 100% (88/88), 527.07 KiB | 2.43 MiB/s, done.
Total 88 (delta 7), reused 0 (delta 0)
remote: Powered By Gitee.com
To https://gitee.com/kklldog/CoreForDocker.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

添加Dockerfile文件

在CoreForDocker下新增一个Dockerfile文件,注意没有任何扩展名。我们需要基于microsoft/dotnet:latest这个镜像构建一个新的镜像。并且在构建的过程中直接对源码进行编译并发布。

FROM microsoft/dotnet:latest
WORKDIR /app
COPY /. /app
RUN dotnet restore
RUN dotnet publish -o /out -c Release
EXPOSE 5000
ENTRYPOINT ["dotnet", "/out/CoreForDocker.dll"]

大概解释下Dockerfile的意思:
FROM microsoft/dotnet:latest:使用dotnet的最新镜像,这个镜像其实对应的应该就是2.2-sdk这个镜像,里面包含了dotnet-core 2.2 sdk
WORKDIR /app:指定工作目录为app
COPY /. /app复制宿主机当前目录的内容到容器的app文件夹
RUN dotnet restore:还原nuget包
RUN dotnet publish -o /out -c Release编译并发布程序集到容器的out目录
EXPOSE 5000:暴露5000端口
ENTRYPOINT [“dotnet”, “/out/CoreForDocker.dll”]:容器启动的时候执行dotnet命令,参数为/out/CoreForDocker.dll


Dockerfile的文件属性设置为始终复制
新建好Dockerfile后git push到代码仓库。

在服务器上构建Docker镜像

这里以Ubuntu为例,ssh登录到服务器后使用git clone命令拉取源代码。

git clone https://gitee.com/kklldog/CoreForDocker.git

进入源码目录

cd CodeForDocker\CodeForDocker

使用docker build命令构建新的镜像,注意不要忘记最后一个’.’

docker build -t image_code4docker .

运行容器

如果以上步骤都没有报错,那么恭喜你镜像已经构建成功了,我们可以使用此镜像运行Docker容器了。

docker run -d --name code4docker -p 5000:5000 -v /ect/localtime:/ect/localtime image_core4docker

使用image_core4docker镜像运行一个名为core4docker的容器,绑定宿主机的5000到容器的5000口。其中需要注意的是-v参数映射宿主机的/ect/localtime文件夹到容器的/ect/localtime文件夹,因为经过实践发现容器中的时区有可能跟宿主机不一致,需要映射宿主机的/ect/localtime让容器的时区跟宿主机保持一致。


访问一下服务器的5000端口,发现能够正确返回数据表示我们的Asp.net Core程序在容器中运行成功了

以后当我们对源码进行修改,并提交后,我们只需在服务器上拉取最新的代码然后使用docker build,docker run命令来再次生成镜像并运行容器。但是手工输入docker build,docker run的命令好像也很麻烦,参数又那么多,太烦了。

使用shell脚本简化操作

为了偷懒不想敲那么长的命令,我们可以构建一个脚本,把命令一次性写好,以后只要运行一次脚本就可以了。
使用vim新建一个publish.sh的文件

vim publish.sh

键盘上按i进入编辑模式,输入以下内容

cd CoreForDocker/CoreForDocker
git pull
docker stop core4docker
docker rm core4docker
docker rmi image_core4docker
docker build -t image_core4docker .
docker run --name core4docker -d -p 5000:5000 -v /etc/localtime:/etc/localtime image_core4docker

以上命令,不光有新建镜像跟运行容器的命令,还有移除原来的容器跟镜像的命令
按ecs进入命令模式,退出保存

:wq

让我们模拟修改一下源代码,并提交到代码仓库

    public IActionResult Index()
    {
        return Content($"Core for docker , {DateTime.Now} , version 2");
    }

再次修改homecontroller的index action,输出内容上新增一个version
ssh登录到服务器,运行publish.sh文件

/bin/bash publish.sh


跑完之后我们再次访问下服务器的5000口,数据返回正确,表示服务器上跑的已经是最新的程序了

总结

通过以上演示我们基本了解如何通过git跟docker配合在Ubuntu服务器上不安装.Net Core SDK来发布.Net Core 程序到容器中运行,并且通过shell脚本的方式再次简化发布。但是尽管这样每次发布都需要ssh到服务器上然后运行脚本,特别是开发环境可能经常需要发布,还是觉得麻烦。有没有什么办法让我们push代码后服务器自动就开始部署最新的代码的到容器中运行了呢?
后面我会介绍下如何通过jenkins跟webhook来做CICD。

.Net Core in Docker – 在容器内编译发布并运行 – Agile.Zhou – 博客园已关闭评论
2019年2月19日 By mikel 分类: ASP.NET, C#

来源: CentOS开发ASP.NET Core入门教程 – 依乐祝 – 博客园

作者:依乐祝
原文地址:https://www.cnblogs.com/yilezhu/p/9891346.html

因为之前一直没怎么玩过CentOS,大多数时间都是使用Win10进行开发,然后程序都部署在Window Server2008或者Window Server2012上!因此想尝试下Linux系统。最后经过选型选了比较流行的CentOS系统。正好,今晚要加班,所以在数据备份的空隙,写了今天这篇关于使用CentOS开发ASP.NET Core的入门教程。干货不多,主要是为了记录自己向Linux迈出第一步的大门。大家将就着看吧!

前言

程序员的江湖一直有这么一个传说,就是入坑的第一个程序都是向世界问好,所以这篇CentOS开发ASP.NET Core入门教程的第一篇也仅仅是搭建环境,然后向世界输出“Hello World!”。

CentOS系统ASP.NET Core开发环境的搭建

这里假设大家已经装了Linux虚拟机或者买了阿里云的Linux服务器。而且在Windows开发机上安装 xshell ,xshell用于SSH连接Linux服务器(当然,你也可以用其他的软件,这么不过多阐述)。下面用xshell连接上你的linux服务。然后开始进入正式的部署吧。

安装.Net Core SDK

要开始构建.Net Core应用程序前,你需要安装.NET Core SDK(软件开发工具包)即可。
具体怎么安装呢?有以下几个步骤:

  1. 添加dotnet 产品Feed(就是为了告诉微软,我们的服务器要使用.net Core sdk了)

    在安装.net sdk之前呢,你需要注册Microsoft密钥,注册产品存储库并安装所需的依赖项。这个步骤每台服务器只需要执行一次既可以了。命令如下所示:

    sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
  2. 安装.Net Core SDK

    首先要安装可用的产品更新,然后才是安装.Net Core SDK。在命令行,分别运行下面的命令。

    sudo yum update 
    y
    sudo yum install dotnet-sdk-2.1
    y

    大家注意一下,有两个“y”的原因是,命令执行的中途会停顿下人,让你确认下是否进行安装,你要输入“y”确认安装才会执行安装的。

在CentOS上创建你的第一个.Net Core 应用程序

  1. 前面安装好.net core sdk以后,我们输入如下命令来看下我们是否安装成功吧!
dotnet --info

1541070786941

如果出现上面的图说明我们已经安装成功了。上面显示有.Net Core的版本信息。

  1. 接下来我们新建一个文件夹名字叫“netcore”用来存放我们的asp.net core应用程序。然后进入这个文件夹
mkdir netcore
cd netcore
  1. 输入如下的命令来创建第一个ASP.NET Core应用程序
    dotnet new console -o myFirstApp
    cd myFirstApp

    dotnet命令为您创建一个新的控制台应用程序。该-o参数为新的应用程序创建一个名为myFirstApp的目录。该cd myFirstApp命令将切换到这个新的应用程序目录。
    然后输入ls命令可以看到下图所示的三个文件:

    1541071244630

    该myFirstApp文件夹中的主文件是 Program.cs。默认情况下,它已包含了向控制台输入“Hello World!”所需的代码。

  2. 使用如下的命令来运行下这个应用程序吧。
    dotnet run

    1541071468709

    如果不出意外的话,大家可以看到,程序向我们输入了Hello World的!
    至此,我们在Centos上的第一个.Net Core程序就跑起来了!

    总结

    今天也是忙里偷闲,利用加班的间隙写了这篇window向CentOS进击的第一篇入门教程!既然ASP.NET Core已经全面跨平台了,那我们也得学会改变,学着使用Linux系统!不管你愿不愿意,这是一个趋势!金庸的江湖已去,而我们程序员的江湖还在继续!多一种技能在身,总归是好事!

CentOS开发ASP.NET Core入门教程 – 依乐祝 – 博客园已关闭评论
2019年2月19日 By mikel 分类: ASP.NET, C#

来源: 使用Visual Studio Code开发.NET Core看这篇就够了 – 依乐祝 – 博客园

在本文中,我将带着大家一步一步的通过图文的形式来演示如何在Visual Studio Code中进行.NET Core程序的开发,测试以及调试。尽管Visual Studio Code的部分功能还达不到Visual Studio的水平,但它实际上已经足够强大来满足我们的日常开发。而且其轻量化,插件化以及跨平台的特性则是VS所不具备的。而且Visual Studio Code还可以通过社区来创建一系列的扩展来增强其功能,且社区已经足够活跃。我们可以期待更多很酷的扩展和功能来增强VS Code,这将使在这个轻量级,跨平台编辑器中的开发.NET Core应用程序更加流畅和有趣。赶紧跟着博主一起开始今天的文章吧!

为什么要写这篇文章?

因为上篇文章也说了,.NET Core已经全面跨平台了,而且我们也在尝试使用Linux了,但是上篇CentOS开发ASP.NET Core入门教程 中使用的CLI进行.NET Core开发的话,感觉很不适应。毕竟从.net过度过来的我们已经习惯了使用Microsoft的Visual Studio进行开发。那么有没有一款媲美Visual Studio的开发工具可以让我们能够在Linux系统上进行高效的.NET Core开发呢?答案是肯定的,因为微软已经开发了一个名为Visual Studio Code的跨平台和开源的文本编辑器。Visual Studio Code是如此强大和令人惊叹,因为它提供了内置的智能提醒,调试功能和Git支持。而且Visual Studio Code提供了强大的插件扩展功能。使得你可以在插件扩展库里面找到满足你需求的插件。如果你没有在他们的扩展库中找到它,那么你还可以自己创建一个插件并使用它。很酷,对吗?那就开始吧!

安装

这部分,我们将讲解如何进行Visual Studio Code的安装,配置以便进行.NET Core的开发

准备工作

  1. 安装.NET Core SDK。具体的安装方式大伙可以点击这里进行查看并进行安装。因为微软的东西都比较傻瓜式,所以这里就不演示了。
  2. 安装Visual Studio Code。您可以从此处 然后根据您的操作系统进行选择下载,不同操作系统的安装过程可能会有所不同 您可以在此处 查看Visual Studio Code的安装说明。还是 因为微软的东西都比较傻瓜式,所以这里就不演示了。1541339022729
  3. 在Visual Studio Code 中安装C# 扩展以便让Visual Studio Code 支持C#的开发,当然你也可以安装其他语言的扩展来进行其他编程语言的开发,比如说python,go等等。为了安装c#的扩展,你可以通过Visual Studio Code左侧工具栏中的Extensions图标或使用键盘快捷键Ctrl + Shift + X打开Extensions视图。在搜索框中搜索C#并从列表中安装扩展程序。如下图所示: 1541339435927

    这里需要注意下,安装完成之后,需要重启下Visual Studio Code才能够使用C#扩展功能。1541339538011
    重启之后会出现如下的界面,表示已经安装好了C#扩展1541339685496

    使用Visual Studio Code开发基本的.NET Core程序

    既然环境都已经准备好了,那么现在我们就开始使用Visual Studio Code开发一个.NET Core应用程序吧!

  4. 在电脑上一个位置创建一个名为DotNetCoreSample的空文件夹,然后右键单击该文件夹,从弹出的菜单中选择“使用Visual Studio Code打开”。这将打开Visual Studio Code,并将选定该文件夹作为工作区。当然也可以通过下图所示的步骤来打开这个文件夹,这个按照你的习惯来操作就好。1541340456205
  5. 使用`Ctrl+Shift+“ 快捷键在 Visual Studio Code 中快速打开终端,如下图所示:

    1541590018735

  6. 接下来我们使用dotnet new console --name DotNetCoreSample 命令来在这个打开的终端里面创建一个基础的控制台程序并进行restore。如下图所示

    1541590248007

  7. 接下来我们打开生成的Program.cs 文件,Visual Studio Code会安装OmniSharp插件,然后会在右下角弹出如下图所示的是否需要生成用来构建以及调试的资产文件的询问窗口,这里点击“是”就会帮我们生成“launch.json”以及“task.json”文件,这些文件将有助于使用Visual Studio代码构建和调试应用程序 。

    1541590405069

    1541590667259

  8. 下面我们修改下Program.cs 文件中的内容,添加下面这行代码。然后保存文件,并把鼠标移动到终端,然后终端cd到我们的项目目录cd DotNetCoreSample。输入dotnet run 然后按下Enter键,可以看到如下所示的内容:

    1541591036238

Visual Studio Code中vscode-solution-explorer解决方案管理器插件的使用

可能很多.neter朋友们刚开始使用Visual Studio Code的时候很不适应各种命令行dotnet命令来创建项目以及解决方案。幸运的是,Visual Studio Code扩展中提供了类似于Visual Studio的解决防范资源管理的插件来解决这个问题。下面我们一步一步的看下如何使用此插件吧!

  1. 打开Visual Studio Code扩展,然后输入vscode-solution-explorer,然后如下图所示进行安装。

    1541591973934

  2. 安装后插件后,VS Code Explorer左侧栏中将多了一个显示名为“SOLUTION EXPLORER”的新窗格。

    1541592290514

  3. 接下来我们使用它来创建解决方案,并在解决方案中添加项目吧。我们按下快捷键Ctrl + Shift + P

    然后选择“Create a new empty solution ” VS Code 将提示我们输入一个解决方案的名称。我们输入一个SimpleCalculator 作为解决方案的名称。

    1541592847941

  4. 现在,VS Code将使用我们提供的名称创建一个空的解决方案。在后台,我们安装的扩展将执行dotnet new sln  命令。您可以在“SOLUTION EXPLORER”窗格中看到空白解解决方案。然后此扩展程序将询问你是否创建模板文件夹请参见下图。如果允许,它将在.vscode / solution-explorer 目录中添加一些模板。

    1541593203311

  5. 现在,让我们向这个空白的解决方案中添加类库和控制台应用程序。右键单击解决方案(在Solution Explorer窗格中),然后从上下文菜单中选择Add new project选项。这将列出.NET CLI提供的可用项目类型(请参见下图)。选择“类库”选项。

    1541593412253

    1541593430198

  6. 系统将询问您将使用哪种语言。选择C#,编辑器将提示输入项目名称。 像我们之前给出的那样给出MathOperations的名称。类库已添加到解决方案中。
  7. 重复相同的步骤并添加名为“Calculator ”的控制台应用程序。请记住从项目模板中选择控制台应用程序。
  8. 现在我们需要在控制台应用程序中添加类库项目的引用。右键单击控制台应用程序项目,然后从上下文菜单中选择“添加引用”选项。由于解决方案中只有两个项目,扩展程序将自动添加另一个项目的引用。如果有两个以上的项目,我们需要从列表中选择项目。

    1541593786278

  9. 导航到类库目录MathOperations。将Class1.cs  类文件重命名为MathOperations.cs。在类中添加一个两个数字的简单简单加法的方法,代码如下:
        public static class MathOperation    
        {    
            public static int Add(int num1, int num2) => num1 + num2;
        }  
  10. 修改导航到Calculator控制台程序并在Program.cs文件中使用类库中的方法。这里大家可以使用Shift + Alt + F快捷键格式化代码。如下所示:
    static void Main(string[] args)
            {
                int num1 = 10;
                int num2 = 20;
                int sum = MathOperation.Add(num1, num2); // Method from class library    
                Console.WriteLine($"{num1} + {num2} = {sum}");
                Console.ReadLine();
            }
  11. 现在,右键单击解决方案资源管理器树中的控制台应用程序项目,然后从上下文菜单中选择“运行”选项。您可以看到.NET CLI将在后台运行应用程序。并在Output窗口中输出结果,如下图所示。

    1541594980618

    1541594999015

Visual Studio Code在.NET Core应用程序中运行测试插件

单元测试是软件开发不可或缺的一部分。这里我不打算详细解释单元测试,因为有很多在线资源。我只给大家介绍如何在.NET Core应用程序中包含单元测试以及可用于运行单元测试的Visual Studio Code的扩展。

  1. 首先让我们该写下数学运算的类库方法
 public static class MathOperation
    {
        public static int Add(int num1, int num2) => num1 + num2;
        public static int Subtract(int num1, int num2) => num1 - num2;

        public static int Multiply(int num1, int num2) => num1 * num2;

        public static int Divide(int num1, int num2) => num1 / num2;
    }
  1. 现在,我们需要在解决方案中添加一个单元测试项目。

我们可以使用.NET CLI或上面提到的Solution Explorer扩展来添加单元测试项目。要通过Solution Explorer扩展添加项目,请右键单击解决方案,然后 从上下文菜单中选择“ 添加新项目 ”。从项目模板中选择xUnit Test Project 并命名为 MathOperationTests。创建测试项目后,将MathOperations类库的引用添加到测试项目中。

如果您使用的是.NET CLI,则需要运行以下命令。

dotnet new xunit -n MathOperationTests  
dotnet add MathOperationTests\MathOperationTests.csproj reference MathOperations\MathOperations.csproj  
dotnet sln SimpleCalculator.sln add MathOperationTests\MathOperationTests.csproj
  1. UnitTest1.cs重命名为OperationTests.cs。也要在代码中更改类名。现在我们将为类库方法添加一些测试。
    public class OperationTests
        {
            [Fact]
            public void AddTwoNumbers_ReturnsSum()
            {
                var num1 = 10;
                var num2 = 20;
                var result = MathOperation.Add(num1, num2);
                Assert.Equal(30, result);
            }
    
            [Fact]
            public void SubtractTwoNumbers_ReturnsDifference()
            {
                var num1 = 20;
                var num2 = 10;
                var result = MathOperation.Subtract(num1, num2);
                Assert.Equal(10, result);
            }
    
            [Fact]
            public void MultiplyTwoNumbers_ReturnsProduct()
            {
                var num1 = 10;
                var num2 = 20;
                var result = MathOperation.Multiply(num1, num2);
                Assert.Equal(200, result);
            }
    
            [Fact]
            public void DivideTwoNumbers_ReturnsQuotient()
            {
                var num1 = 20;
                var num2 = 10;
                var result = MathOperation.Divide(num1, num2);
                Assert.Equal(2, result);
            }
        }
  2. 现在,我们需要运行我们创建的测试。我们为此使用.NET CLI。打开终端。导航到MathOperationTests目录。输入dotnet test命令。我们将获得以下输出。

    1541596760373

  3. 如您所见,输出信息量较少。如果我们在Visual Studio中有类似于Test Explorer的东西来执行我们的单元测试并查看结果,那将会很好。好消息是有一个名为.NET Core Test Explorer的Visual Studio Code插件。下面按照下图所示在Visual Studio代码中安装此扩展吧。这里不过多说明了

    1541597219891

  4. 安装扩展程序后,您可以在左侧活动栏中看到一个烧杯图标。单击该图标,您将看到测试的侧栏面板,其中列出了项目中发现的单元测试。测试项目将显示在按命名空间和类分组的树视图中。您还可以看到每个测试的“运行”按钮和顶部的“全部运行”按钮。单击Run All按钮,您可以看到正在执行的所有测试及其结果。

    1541597348658

  5. 我们可以看到所有测试都已通过,并在测试资源管理器窗格中标有绿色勾号。现在让我们让测试失败。我将更改Add方法的逻辑以使测试失败。
     public static int Add(int num1, int num2) => num1 - num2;//这里有bug
  6. 现在再次运行测试。我们可以看到我们对Add方法的测试失败,并在test explorer窗格中用红色符号标记。

    1541597509689

  7. 如果我们导航到我们编写的测试方法,我们可以看到它现在在Assert方法中有一个红色的波浪下划线。如果我们将鼠标悬停在该波浪线上,将显示一个信息框,显示测试的实际值和预期值。VS代码的底部面板(终端所在的面板)的“ 问题”选项卡中显示相同的信息。这可以在下图中看到。

    1541597599699

  8. 修复错误并再次运行测试,以便所有测试都通过,我们可以再次看到绿色标记。

Visual Studio Code中顺畅的调试.NET Core应用程序

在这部分,我们将了解如何在Visual Studio Code中顺畅的调试.NET Core应用程序。为了在Visual Studio Code中调试.NET Core应用程序,我们需要为VS Code安装C#扩展。(上面我们已经安装过了)

  1. 我们首先在Calculator控制台程序的Program.cs文件中加入断点。与Visual Studio类似,我们可以通过单击源代码文件的左边距,或者将光标放在一行代码上并按F9,在源代码中设置行断点。断点在编辑器的左边缘显示为红点。
  2. 要开始调试,请按F5。这将自动将调试器附加到我们的Calculator应用程序来启动应用程序。我们可以看到执行在我们设置的断点处停止,这有助于我们在调试时了解当前的程序状态。

    1541598520046

    这里需要注意下,需要修改launch.json中的对应路径以及项目名称为Calculator。

    1541598690693

  3. 我们可以看到VS Code的Debug视图在编辑器的左侧打开。Debug视图显示与调试相关的所有信息。我们还可以注意到编辑器顶部出现了一个调试工具栏。调试时,调试工具栏可用于代码导航选项。这里调试试图的大部分功能跟vs2017差不多,因此这里不做过多地阐述了。

总结

在本文中,我已经为大家一步一步的通过图文教程解释了如何在Visual Studio Code中进行.NET Core程序的开发,测试以及调试。赶紧下载一个试试吧!你会发现你会越来越喜欢他的!
本文参考:https://www.c-sharpcorner.com/article/create-a-net-core-development-environment-using-visual-studio-code2/

使用Visual Studio Code开发.NET Core看这篇就够了 – 依乐祝 – 博客园已关闭评论
2019年2月18日 By mikel 分类: PHP, 架构设计

首先了解一个方法: 使用docker exec进入Docker容器 docker在1.3.X版本之后还提供了一个新的命令exec用于进入容器,这种方式相对更简单一些,下面我们来看一下该命令的使用: 接

来源: docker完整配置nginx+php+mysql – 冒雨ing – 博客园

首先了解一个方法:

使用docker exec进入Docker容器

docker在1.3.X版本之后还提供了一个新的命令exec用于进入容器,这种方式相对更简单一些,下面我们来看一下该命令的使用:

sudo docker exec --help

 

接下来我们使用该命令进入一个已经在运行的容器

$ sudo docker ps  
$ sudo docker exec -it 775c7c9ee1e1 /bin/bash

 

一. 配置nginx

查找 Docker Hub 上的 nginx 镜像

runoob@runoob:~/nginx$ docker search nginx
NAME                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                     Official build of Nginx.                        3260      [OK]       
jwilder/nginx-proxy       Automated Nginx reverse proxy for docker c...   674                  [OK]
richarvey/nginx-php-fpm   Container running Nginx + PHP-FPM capable ...   207                  [OK]
million12/nginx-php       Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   67                   [OK]
maxexcloo/nginx-php       Docker framework container with Nginx and ...   57                   [OK]
webdevops/php-nginx       Nginx with PHP-FPM                              39                   [OK]
h3nrik/nginx-ldap         NGINX web server with LDAP/AD, SSL and pro...   27                   [OK]
bitnami/nginx             Bitnami nginx Docker Image                      19                   [OK]
maxexcloo/nginx           Docker framework container with Nginx inst...   7                    [OK]
...

这里我们拉取官方的镜像

runoob@runoob:~/nginx$ docker pull nginx

等待下载完成后,我们就可以在本地镜像列表里查到 REPOSITORY 为 nginx 的镜像。

runoob@runoob:~/nginx$ docker images nginx
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              555bbd91e13c        3 days ago          182.8 MB

创建并运行容器:
docker run --name mynginx -p 80:80 -v /var/www:/var/www -v /usr/local/nginx/conf/conf.d:/etc/nginx/conf.d -d nginx

注意:

-v 添加文件映射关系,这样在宿主机上更改的文件可以直接映射到容器中。这里的目录根据自己实际情况进行映射。

创建并运行容器后,docker内的nginx即启动成功,无需进入docker内部再次启动nginx, 否则会提示80等端口被占用,因为nginx已经启动。

这时候便可以访问nginx配置的域名验证了。

我这里映射的conf.d主要包含nginx的配置文件,php的配置信息为:

复制代码
# php
server {
    charset utf-8;
    client_max_body_size 128M;

    listen 80; ## listen for ipv4
    #listen [::]:80 default_server ipv6only=on; ## listen for ipv6

    server_name www.baidu.com;
    root        /var/www;
    index       index.php;

    location / {
        #-e表示只要filename存在,则为真
        if (!-e $request_filename){
            rewrite  ^(.*)$  /index.php?s=$1  last;
            break;
        }
        # Redirect everything that isn't a real file to index.php
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # uncomment to avoid processing of calls to non-existing static files by Yii
    #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
    #    try_files $uri =404;
    #}
    #error_page 404 /404.html;

    # deny accessing php files for the /assets directory
    location ~ ^/assets/.*\.php$ {
        deny all;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 172.17.0.3:9000;
        #fastcgi_pass unix:/var/run/php5-fpm.sock;
        try_files $uri =404;
    }

    location ~* /\. {
        deny all;
    }
}
复制代码

注意最后面的fastcgi_pass的ip地址,在php配置常见问题有详细介绍。

 

二. php配置

查找Docker Hub上的php镜像

runoob@runoob:~/php-fpm$ docker search php
NAME                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
php                       While designed for web development, the PH...   1232      [OK]       
richarvey/nginx-php-fpm   Container running Nginx + PHP-FPM capable ...   207                  [OK]
phpmyadmin/phpmyadmin     A web interface for MySQL and MariaDB.          123                  [OK]
eboraas/apache-php        PHP5 on Apache (with SSL support), built o...   69                   [OK]
php-zendserver            Zend Server - the integrated PHP applicati...   69        [OK]       
million12/nginx-php       Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   67                   [OK]
webdevops/php-nginx       Nginx with PHP-FPM                              39                   [OK]
webdevops/php-apache      Apache with PHP-FPM (based on webdevops/php)    14                   [OK]
phpunit/phpunit           PHPUnit is a programmer-oriented testing f...   14                   [OK]
tetraweb/php              PHP 5.3, 5.4, 5.5, 5.6, 7.0 for CI and run...   12                   [OK]
webdevops/php             PHP (FPM and CLI) service container             10                   [OK]
...

这里我们拉取官方的镜像,标签为5.6-fpm

runoob@runoob:~/php-fpm$ docker pull php:5.6-fpm

等待下载完成后,我们就可以在本地镜像列表里查到REPOSITORY为php,标签为5.6-fpm的镜像。

runoob@runoob:~/php-fpm$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php                 5.6-fpm             025041cd3aa5        6 days ago          456.3 MB

创建并运行php容器:

docker run -p 9000:9000 --name  phpfpm -v /var/www:/var/www -d php:5.6-fpm

注意这里一定要创建文件映射,或者php容器内有对应的php代码。上一步nginx的文件映射,在这里是找不到的。所以如果没有文件映射,127.0.0.1:9000 在此容器内就找不到文件 。

 

常见问题:

启动php容器后,如果访问nginx为:502 Bad Gateway

尝试以下方法:

查看php镜像的ip地址

docker inspect --format='{{.NetworkSettings.IPAddress}}' phpfpm

如:192.168.4.202

那么修改nginx的conf配置文件,使fastcgi_pass的值为 192.168.4.202:9000
vim /docker/nginx/conf.d/default.conf
fastcgi_pass 192.168.4.202:9000;

重启nginx容器后,就可以正常访问。

 

三. mysql配置

查找Docker Hub上的mysql镜像

runoob@runoob:/mysql$ docker search mysql
NAME                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                    MySQL is a widely used, open-source relati...   2529      [OK]       
mysql/mysql-server       Optimized MySQL Server Docker images. Crea...   161                  [OK]
centurylink/mysql        Image containing mysql. Optimized to be li...   45                   [OK]
sameersbn/mysql                                                          36                   [OK]
google/mysql             MySQL server for Google Compute Engine          16                   [OK]
appcontainers/mysql      Centos/Debian Based Customizable MySQL Con...   8                    [OK]
marvambass/mysql         MySQL Server based on Ubuntu 14.04              6                    [OK]
drupaldocker/mysql       MySQL for Drupal                                2                    [OK]
azukiapp/mysql           Docker image to run MySQL by Azuki - http:...   2                    [OK]
...

这里我们拉取官方的镜像,标签为5.6

runoob@runoob:~/mysql$ docker pull mysql:5.6

等待下载完成后,我们就可以在本地镜像列表里查到REPOSITORY为mysql,标签为5.6的镜像。

runoob@runoob:~/mysql$ docker images |grep mysql
mysql               5.6                 2c0964ec182a        3 weeks ago         329 MB

创建并运行MySQL容器:

docker run -p 3306:3306 --name mysql -v /usr/local/mysql:/etc/mysql/sqlinit -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6

这里的文件映射主要目的是把宿主机的sql数据库数据文件映射到docker mysql容器,方便导入,注意这里mysql容器的目录不能是已有的目录,否则会覆盖。

注意:

这里创建容易已经有了my.cnf,无需自己添加。

 

 拓展

使用外部工具navicat连接docker 内mysql

mysql的host 填写docker内的IP,获取方式为:

1 docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql

填写ssh连接信息:

即可连接成功!

 

注意:

docker的容器启动顺序问题会导致容器的IP地址不一致,如果在连接数据库和fastcgi处有用到容器的IP,要注意容器的启动顺序。

重启容器:docker restart 容器名/容器ID

关闭容器:docker stop xxx

开启容器:docker start xxx

查看正在运行的容器:docker ps

查看所有容器(包括未运行的容器): docker ps -a

创建并运行容器: docker run

 

—————————————

 

常见报错:

1.  thinkphp报错 Undefined class constant ‘MYSQL_ATTR_INIT_COMMAND’

缺少pdo_mysql扩展,链接数据库失败

找到php.ini,docker中在/usr/local/etc/php中,复制一份php.ini,增加 extension=pdo_mysql.so  ,重启phpfpm。

如果还不行,访问phpinfo页面,查看是否有pdo_mysql

如果没有,说名扩展不存在,需要编译。

编译方法如下:

可以通过两种方式实现
方式一(未验证):

pecl pdo_msql

方式二(已验证可行):

到docker的php容器中,在php文件夹下:

docker-php-ext-install pdo pdo_mysql

如果报 /usr/local/bin/docker-php-ext-enable: cannot create /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini: Directory nonexistent
解决方案:
直接在/usr/local/etc/php目录下面新建 conf.d目录和对应的docker-php-ext-pdo_msql.ini文件
其中docker-php-ext-pdo_msql.ini的内容为:
extension=pdo_mysql.so

 

2. thinkphp 报错 _STORAGE_WRITE_ERROR_:./Application/Runtime/Cache/Home/4e64ea6a2012f26b832b14cbc2152b28.php

是因为服务器缓存文件夹的操作权限不够,即Runtime没有权限,把缓存文件全部删除,再给Runtime777权限就行了

sudo chmod 777 Runtime 或者直接对代码库最外层设置777权限

 

3. thinkphp验证码图片显示不出来

缺少gd扩展,安装:

docker-php-ext-install gd

可能以下报错:

If configure fails try --with-webp-dir=<DIR>
If configure fails try --with-jpeg-dir=<DIR>
configure: error: png.h not found.

安装:

apt-get install libpng-dev libjpeg-dev

再次执行:

// 增加freetype配置
docker-php-ext-configure gd --enable-gd-native-ttf --with-freetype-dir=/usr/include/freetype2 --with-png-dir=/usr/include --with-jpeg-dir=/usr/include

// 安装
docker-php-ext-install gd

php.ini增加php_gd2.so

phpinfo中显示gd库

注意如果phpinfo的gd库中没有freetype的支持,验证码依然显示不出来, 会报错:

Call to undefined function Think\imagettftext()

 

如果gd库中没有freeType,则按照以下步骤进行:

docker-php-ext-configure gd --enable-gd-native-ttf --with-freetype-dir=/usr/include/freetype2 --with-png-dir=/usr/include

重新编译:
docker-php-ext-install gd

如果报错:

configure: error: freetype-config not found.

运行: apt-get -y install libfreetype6-dev ,然后再继续运行上面的命令。

gd库中有了freetype,则验证码显示正常了:

docker完整配置nginx+php+mysql – 冒雨ing – 博客园已关闭评论
备案信息冀ICP 0007948