ORM之炀,打造自已独特的开发框架CRL - hubro - 博客园

mikel阅读(869)

来源: ORM之炀,打造自已独特的开发框架CRL – hubro – 博客园

ORM一直是长久不衰的话题,各种重复造轮子的过程一直在进行,轮子都一样是圆的,你的又有什么特点呢?

CRL这个轮子造了好多年,功能也越来越标准完备,在开发过程中,解决了很多问题,先上一张脑图描述CRL的功能

开发框架的意义在于

  • 开发更标准,更统一,不会因为不同人写的代码不一样
  • 开发效率更高,无需重新造轮子,重复无用的代码,同时简化开发流程
  • 运行效率得到控制,程序稳定性得到提高

围绕这几点,抛开常规的增删改查,我们来讲些与众不同的

1.与众不同之一,动态数据源,天生适合分库分表

可动态配置的功能总比静态的灵活,扩展性强

目前看到的框架多数访问对象实例化都类似于

var context = new MsSqlContext(ConnectionString);

在对象初始时,就绑定上了数据库连接串, 这样写没什么问题,但是不好扩展
如:需要动态切换库,表,根据租户信息访问不同的数据库,或不同类型的数据库,或是读写分离,这时,急需处理的技术问题就来了,分库分表的解决方案,读写分离的方案
在数据连接绑定的情况下,这种问题很不好解决
又或者传入多个连接串,在调用时,手动选择调用的库或表,对于这种方式,只能说耦合太严重,得关心配置,又得关心调用,在CRL之前的版本里,有这样实现过,弃用了

然而根据IOC的理念,这种问题也不是不好解决,让数据访问对象抽象化实现就能办到了
数据查询方法不再直接调用数据访问对象,而是调用抽象工厂方法,由抽象工厂方法来实例化访问对象,过程表示为

数据查询方法(组件内) => 抽象工厂(组件内) => 抽象实现(组件外)

基于这样的理念,CRL在设计之初,就使用了的这样的方式,以代码为例

!数据访问实现

以下实现了分库分表和mongoDB切换

以下在程序启动时初始

复制代码
var builder = new CRL.SettingConfigBuilder();
            builder.UseMongoDB();//引用CRL.Mongo 使用MongoDB
                                 //注册自定义定位,按MemberSharding传入数据定义数据源位置
                                 //注册一
            builder.RegisterLocation<Code.Sharding.MemberSharding>((t, a) =>
            {
                var tableName = t.TableName;
                if (a.Name == "hubro")//当名称为hubro,则定位到库testdb2 表MemberSharding1
                {
                    tableName = "MemberSharding1";
                    return new CRL.Sharding.Location("testdb2", tableName);
                }
                //返回定位库和表名
                return new CRL.Sharding.Location("testdb", tableName);
            });
            //注册二
            builder.RegisterDBAccessBuild(dbLocation =>
            {
                if (dbLocation.ManageName == "mongo")
                {
                    var conn = CRL.Core.CustomSetting.GetConfigKey("mongodb");
                    return new CRL.DBAccessBuild(DBType.MongoDB, conn);
                }
                return null;
            });
            //注册三
            builder.RegisterDBAccessBuild(dbLocation =>
            {
                //自定义定位,由注册一传入
                if (dbLocation.ShardingLocation != null)
                {
                    return new CRL.DBAccessBuild(DBType.MSSQL, "Data Source=.;Initial Catalog=" + dbLocation.ShardingLocation.DataBaseName + ";User ID=sa;Password=123");
                }
                return new CRL.DBAccessBuild(DBType.MSSQL, "server=.;database=testDb; uid=sa;pwd=123;");
            });
复制代码

 

!数据访问类,类似于仓储的形式,根据实际业务实现
定位使用示例

复制代码
public class MemberManage : CRL.Sharding.BaseProvider<MemberSharding>
{
}
var instance=new MemberManage();
instance.Add(new MemberSharding(){Name="hubro"});
复制代码

根据定位规则 运行到注册一,此数据将会插入到 库testdb2 表MemberSharding1

常规切换示例

1
2
3
4
5
6
public class MongoDBTestManage : CRL.BaseProvider<MongoDBModel2>
{
    public override string ManageName => "mongo";
}
var instance=new MongoDBTestManage();
instance.Add(new MongoDBModel2(){name="hubro"});

根据数据访问规则,运行到注册二,此数据将会插入mongodb

可以看到,在上面代码中,没有看到任何数据连接串的传入,数据的访问都由初始时动态分配,对于方法调用是不透明的,调用者不用关心数据源的问题

2.与众不同之二,表结构自动维护

在新技术的支持下,程序和数据库的绑定关系越来越模糊,现在可能是用的SQLServer,回头可能改成MySQL了,或者改成mongoDB
依赖数据库开发变成越来越不可取,效率也很低
再后来出现了DBFirst方式,虽解决了部份问题,但也很麻烦,如:

建立数据库模型=>导入数据库=>T4模版生成代码(修修补补)

而使用CRL后,过程一步到位,在别人还在用PM设计表结构索引时,你已经设计好了业务结构,效率杠杠的

编写实体类,实现对象访问=>调试运行,自动创建表结构(关键字,长度,索引)

同时,CRL还提供了手动维护方法,使能够按实体结构重建/检查数据表
也提供了对象结构文档导出,不用提心文档的问题
详细介绍看这里
https://www.cnblogs.com/hubro/p/6038118.html

3.与众不同之三,动态缓存

使用缓存可以大大提高程序的运行效率,使用REDIS或MONGODB之类的又需要额外维护
对于单应用程序,程序集内缓存非常有用
CRL内置了缓存实现和维护
只需按方法调用就行了,缓存创建维护全自动
如:
从数据库查

var item = instance.QueryItem(b => b.Id==1)

从缓存查

var item = instance.QueryItemFromCache(b=>b.Id==1);

也支持按查询自定义缓存

复制代码
var query = Code.ProductDataManage.Instance.GetLambdaQuery();
//缓存会按条件不同缓存不同的数据,条件不固定时,慎用
query.Where(b => b.Id < 700);
int exp = 10;//过期分钟
query.Expire(exp);
var list = query.ToList();
复制代码

 

基于这样的形式,可以将所有查询都走缓存,再也不用担心数据库查询效率了,简值中小项目开发利器
详细介绍看这里
https://www.cnblogs.com/hubro/p/6038540.html

4.与众不同之四,应对复杂查询

因为没有查询分支的概念,处理复杂的查询,一票ORM估计得退场了,虽然合理的结构设计会减少查询复杂度,但谁能保证呢
CRL查询分支过程如下

主查询 => CreateQuery子查询 => 返回匿名对象筛选LambdaQueryResultSelect => 主查询嵌套子查询 => 返回结果

理论上只要符合调用逻辑,可以无限嵌套
示例:

复制代码
var q1 = Code.OrderManage.Instance.GetLambdaQuery();//主查询
            var q2 = q1.CreateQuery<Code.ProductData>();//创建一个子查询
            q2.Where(b => b.Id > 0);
            var view = q2.CreateQuery<Code.Member>().GroupBy(b => b.Name).Where(b => b.Id > 0).Select(b => new { b.Name, aa = b.Id.COUNT() });//GROUP查询
            var view2 = q2.Join(view, (a, b) => a.CategoryName == b.Name).Select((a, b) => new { ss1 = a.UserId, ss2 = b.aa });//关联GROUP
            q1.Join(view2, (a, b) => a.Id == b.ss1).Select((a, b) => new { a.Id, b.ss1 });//再关联
            var result = view2.ToList();
            var sql = q1.ToString();
复制代码

生成SQL打印如下

复制代码
SELECT t1.[Id] AS Id,
t2.[ss1] AS ss1
FROM [OrderProduct] t1 with(nolock)
INNER JOIN
(SELECT t2.[UserId] AS ss1,
t3.[aa] AS ss2
FROM [ProductData] t2 with(nolock)
INNER JOIN
(SELECT t3.[Name] AS Name,
COUNT(t3.Id) AS aa
FROM [Member] t3 with(nolock)
WHERE (t3.[Id]>@par1)
GROUP BY t3.[Name]) t3 ON (t2.[CategoryName]=t3.[Name])
WHERE (t2.[Id]>@par0) ) t2 ON (t1.[Id]=t2.[ss1])
复制代码

 

不管是JOIN后再GROUP,还是GROUP后再GROUP,还是GROUP后再JOIN,通通不是问题
详细介绍看这里
https://www.cnblogs.com/hubro/p/6096544.html

5.与众不同之五,查询抽象,非关系型数据库支持

通过对Lambda表达式的解析,可以实现不同的查询转换,如MongoDB,或ElasticSearch(目前只实现了MongoDB)
有人问,这样有什么用呢?
好处就是,在CRL框架下,一套LambdaQuery走天下,不用写各种差异很大的查询方法了,在动态数据源的支持下,数据拆分游刃有余
如:
之前有个报表存在MSSQL里,发现数据量太大了,查询慢,改由MongoDB,程序不用怎么调整,直接在配置里改为MongoDB即可

以MongoDB为例

CRLLambdaQuery=>CRLExpression=>BsonDocument=>MongoDB

在[数据访问实现]示例中,演示了如何切换到MongoDB
代码实现见项目:CRL.Mongo

6.题外之六,请使用仓储模式

在上文提到,好多框架会直接返回一个数据访问对象,如

var obj1context.Query<TestEntity>(b=>b.Id==1).ToSingle();

然而这样会导致滥用,直接在WEB层用,在Service层随意用,如

var obj2=context.Query<TestEntity2>(b=>b.Id==1).ToSingle();
var obj3=context.Query<TestEntity3>(b=>b.Id==1).ToSingle();

某一天,TestEntity3要换库了,查找一下引用,傻眼了,上百个引用(接手别人的项目,亲身体验过这种痛苦,一个个改)
好在CRL开始就杜绝了这种情况发生,对据的访问必须通过BaseProvider实现,而BaseProvider就是一个仓储的形式

7.题外之七,查询效率

ORM效率无非分两点,实体映射效率和语法解析效率,

对于映射反映在,一次返回多行数据,转换为实体集合

对于语法解析效率,按参数调用多次,返回一行数据,转换为实体

测式程序和SQL为本机,CPU空闲正常,2核6G服务器

一张图表明一切(不同机器实际情况可能有差异)

CRL效率虽不是最高的,但也不是最差的,测试项目见:

https://github.com/hubro-xx/CRL5/tree/master/Test/TestConsole

 

大概列举了以上几项,还有好多特有的东西,轮子好不好,东西南北滚滚试试

CRL开发框架虽然写好长时间,但一直在Debug状态中, 最近又升级了,分离了数据访问层,不同数据库引用不同的数据访问层,数据访问层实现也很简单,只需要写两个文件,如MySql,实现MySqlHelper和MySQLDBAdapter
见:https://github.com/hubro-xx/CRL5/tree/master/CRL.Providers/CRL.MySql
同时,版本也升级到5.1,项目结构发生了改变

源码地址:https://github.com/hubro-xx/CRL5

CRL目前.NET版本为.net 4.5, 有时间了再整理整理netstandard版本

除了ORM,CRL还带 动态API,RPC,WebSocket,api客户端代理实现
https://www.cnblogs.com/hubro/p/11652687.html
微服务注册,发现,调用集成参见:
https://github.com/hubro-xx/CRL5/blob/master/Consul/ConsulTest/Program.cs

嵌套事务(一):.NET中嵌套事务运用的一点思考_邓福勇-CSDN博客

mikel阅读(770)

来源: 嵌套事务(一):.NET中嵌套事务运用的一点思考_邓福勇-CSDN博客

说实际情形:

由于一个操作中分两步完成,不妨定义为 Method1(),Method2()。只有当一两步都成功执行时,整个操作才算完成,否则要回滚所有数据。

 

一开始,我的实现思路是:

Operate()

{

创建事务连接,开始事务…..

 

If(Method1() 成功&& Method2() 成功)

{ 事务执行成功 }

Else

{

事务回滚,执行不成功

}

 

关闭事务,连接….

}

说明:Method1(),Method2()是独立的方法,里面也是事务。

一开始,想当然的认为没问题,简单测试也没什么问题。

但实际上是有问题的。问题在哪儿呢?

 

不多说,假设Method1()成功,Method2()失败。会出现什么后果:Operate()

回滚,Method2()回滚,Method1()不回滚(为什么,每个方法内,都new了一个新的事务对象,是独立于外部事务的)。

 

所以换了一下思路,只有硬来了

 

Operate()

{

创建事务连接,开始事务…..

//1 将Method1()的实现代码写在这儿

…….

成功(不提交),继续下走;不成功,回滚。

 

//2 将Method2()的实现代码写在这儿–有问题的(2011-1-17注)

…….

成功(不提交),继续下走;不成功,回滚。

// 3

在这里才确定了整个事务成功。

……

}

 

 

所以在.NET 中嵌套事务实现几个动作同时进行时,一定要小心。本文的思路是,将所有的分步操作,在一个事务中实现,也就没了嵌套事务,但实际的结果是一样,并提高了性能。只是以代码的长度作为代价的,呵呵。

当然,有时允许成功了的部分不回滚,那第一种情形也就适用了。

———————————–2011分隔线——————————————–

 

现在再来看上来的东西,可以改进: 接着讲更实际些的。

1:跨库操作(来源于两个不同的数据库) demo:

SQLConnection connConsDB = dboConsDB.CreateConnection as SQLConnection;
SqlConnection connStatDB = dboStatDB.CreateConnection as SqlConnection;

connConsDB.Open();
connStatDB.Open();

using (SqlTransaction tranConsDB = connConsDB.BeginTransaction())
{
using (SqlTransaction tranStatDB = connStatDB.BeginTransaction())
{
try
{
//ip数据操作
OperatIp(tranConsDB, tranStatDB);
//cookie数据操作
OperatCookie(tranConsDB, tranStatDB);

tranConsDB.Commit();
tranStatDB.Commit();

result.IsSuccess = true;
result.Message = “广告注册用户激活游戏数据操作成功”;
}
catch (Exception ex)
{
exceptionDBLog.InsertExceptionLog(ex);

tranConsDB.Rollback();
tranStatDB.Rollback();

result.IsSuccess = false;
result.Message = “广告注册用户激活游戏数据操作失败”;
}
}
}

 

2:多步操作为一事务(即我们刚开始讨论的东西)

SqlConnection con = dbo.CreateConnection as SqlConnection;
con.Open();
SqlTransaction tran = con.BeginTransaction();

try
{
//获取数据源
DataResult resultADClickIp = GetADClickIpResult();
DataResult resultRegisterTmp = GetRegisterTmpResult();
DataResult resultRechargeExchangeTmp = GetRechargeExchangeTmpResult();
DataResult resultWenDaoGameActiveTmp = GetWenDaoGameActiveTmp();
DataResult resultMHSSGameActivateTmp = GetMHSSGameActivateTmp();
DataResult resultJDFJGameActivateTmp = GetJDFJGameActivateTmp();
DataResult resultDanGameActivateTmp = GetDanGameActivateTmp();
DataResult resultAdVisitLogTmp = GetAdVisitLog();
DataResult resultPageViewLogTmp = GetPageViewLog();

//转移数据
MoveADClickIpTbl(resultADClickIp, tran);//广告点击IP表(第二层核心数据)[定期转移])

MoveRegisterTmpTbl(resultRegisterTmp, tran); //注册用户临时表(第二层)[保留3个月] 数据

MoveMHSSGameActivateTmpTbl(resultMHSSGameActivateTmp, tran);// 转移**游戏激活日志临
MoveJDFJGameActivateTmpTbl(resultJDFJGameActivateTmp, tran);// 转移**游戏激活日志临时
MoveDanGameActivateTmpTbl(resultDanGameActivateTmp, tran);// 转移**游戏激活日志临时表
MoveAdVisitLogTmpTbl(resultAdVisitLogTmp, tran);//转移广告访问日志数据源
MovePageViewLogTmpTbl(resultPageViewLogTmp, tran);//站点日志部分
tran.Commit();
return true;
}
catch (Exception ex)
{
tran.Rollback();
exceptionDBLog.InsertExceptionLog(ex);
return false;
}

 

SQLServer 事务相关:《嵌套事务(一):.NET中嵌套事务运用的一点思考》

《嵌套事务(二):SQLServer中嵌套事务使用》

《SqlServer 嵌套事务机制 测试 》
————————————————
版权声明:本文为CSDN博主「xiaoyong322」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dfyong/article/details/5684381

SqlServer嵌套事务机制 测试_邓福勇-CSDN博客

mikel阅读(786)

来源: SqlServer嵌套事务机制 测试_邓福勇-CSDN博客

SQLServer 事务相关:《嵌套事务(一):.NET中嵌套事务运用的一点思考》

《嵌套事务(二):SQLServer中嵌套事务使用》

《 SQLServer嵌套事务机制 测试  》

今天我们主研究一下SQLServer中嵌套事务使用。代码能说明大多数问题,看代码。
1.嵌套事务提交原理测试

结果:

Trancount before transaction: 0
After first BEGIN TRAN: 1
After second BEGIN TRAN: 2
After first COMMIT TRAN: 1
After second COMMIT TRAN: 0

我们可以得出:

1.可以看到每一个BEGIN TRAN语句都会使@@TRANCOUNT增加1;

2.每一个COMMIT TRAN语句都会使@@TRANCOUNT减少1;

3.如前所述,一个值为0的@@TRANCOUNT意味着没有打开的事务;

4.因此,在@@TRANCOUNT值从1降到0时结束的事务发生在最外层事务提交的时候。

2. 嵌套事务回滚
2.1  嵌套事务回滚最外面事务,对内部事务有什么影响?
我们再来看一段代码:

结果:没有数据。

现在看来:无论数据是否提交,只要最外层回滚了就会导致所有内部所有嵌套类回滚。

2.2 嵌套事务回滚内部嵌套事务呢?
再看一段代码:

结果:

有异常信息:

(1 行受影响)
消息 6401,级别 16,状态 1,第 9 行
无法回滚 InProc。找不到该名称的事务或保存点。

(1 行受影响)

(2 行受影响)

我们可以看到:ROLLBACK TRANSACTION InProc 是错误的。原因是没有保存还原点 InProc。代码应该改为如下(具体原因请往下看):

BEGIN TRANSACTION InProc
save tran InProc;
INSERT INTO #TestTrans VALUES (1,’aaaa’);
ROLLBACK TRANSACTION InProc;
操作前保存好回滚点(save tran InProc),回滚时指定当时保存的位置,SqlServer才知道回滚到哪儿去。

3. 事务原理
往下读之前必须了解:全局变量@@trancount 可以确定是否存在打开的事务及其嵌套的深度。

 

提交的事务不能撤销或回滚。

当不存在打开的事务时,@@trancount 等于 0。

执行 begin tran [tranName]语句将 @@trancount 增加 1。

执行commit tran [tranName]语句将 @@trancount 减小 1。

执行 rollback tran  会回滚整个事务并设置@@trancount 为 0。

 

执行 ” rollback tran  tranName”语句时有两种情况:

if(tranName 之前 是用 ” Save Tran tranName” )  @@trancount值不变

否则,@trancount 减小1

 

具体测试代码:

— 创建临时表
CREATE TABLE #TestTrans(Cola INT PRIMARY KEY,
Colb varchar(20) NOT NULL);

select @@TRANCOUNT ‘未开外部事务’;

/* 外部事务 */
BEGIN TRANSACTION OutOfProc;
select @@TRANCOUNT ‘开外部事务’;

–内部事务
BEGIN TRANSACTION InProc

select @@TRANCOUNT ‘开内部事务1’;

save tran InProc;

select @@TRANCOUNT ‘保存内部事务1′;
INSERT INTO #TestTrans VALUES (1,’aaaa’);
ROLLBACK TRANSACTION InProc;

select @@TRANCOUNT ‘回滚内部事务1′;

–内部事务2
BEGIN TRANSACTION InProc2
INSERT INTO #TestTrans VALUES (2,’222’);

–内部事务21
BEGIN TRANSACTION InProc21
select @@TRANCOUNT ‘开内部事务21′;
INSERT INTO #TestTrans VALUES (3,’2422’);
COMMIT TRANSACTION InProc21;
select @@TRANCOUNT ‘提交内部事务21’;

COMMIT TRANSACTION InProc2;
select @@TRANCOUNT ‘提交内部事务2’;

/* 提交外部事务 */
COMMIT TRANSACTION OutOfProc;

select @@TRANCOUNT ‘提交外部事务’;

SELECT * FROM #TestTrans;

drop table #TestTrans
结果:

其他:
保存事务回滚点–可以有选择的提交或回滚内部嵌套事务。
思路

检查@@TRANCOUNT的值,以此来确定是否需要开始一个事务。如果@@TRANCOUNT大于0,则不开启新事务,只需要保存的个回滚位置即可;否则,开启新事务。下面是操作:

 

1.保存回滚点:

declare @trancount int –commit,rollback只控制本存储过程
set @trancount = @@trancount
if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/
begin tran curtran–当前事务点,rollback、commit都从这里开始
else
save tran curtran
2. 回滚指定“回滚点”:

if(@error <> 0 or @pay_way_error = 0) –@pay_way_error 决定了是否需要回滚
begin
rollback tran curtran
set @result = -1 –异常
end

if(@error <> 0 or @pay_way_error = 0) –@pay_way_error 决定了是否需要回滚
begin
rollback tran curtran
set @result = -1 –异常
end

————————————————
版权声明:本文为CSDN博主「xiaoyong322」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dfyong/article/details/7355426

嵌套事务(二):SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题_邓福勇-CSDN博客

mikel阅读(741)

来源: 嵌套事务(二):SqlServer中嵌套事务使用–事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题_邓福勇-CSDN博客

今天又遇见了以前遇到的问题,一个聪明的人不应该将同一个错误出现两次错误,但事实上来,在我身上出了好几次,就其原因是对SQLServer 事务的提交与回滚没有深刻的认识。

问题:
1. System.Data.SQLClient.SQLException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

2. EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。

后面的内容,是我之前写的东西,主要是一些测试代码,但是呢,我没有很深入的理解。现在直接说清楚本质的东西,把后面的精华再提上来说。

提交的事务不能撤销或回滚。
当不存在打开的事务时,@@trancount 等于 0。
执行 begin tran [tranName]语句将 @@trancount 增加 1。
执行commit tran [tranName]语句将 @@trancount 减小 1。
执行 rollback tran  会回滚整个事务并设置@@trancount 为 0。
执行 ” rollback tran  tranName”语句时有两种情况:
if(tranName 之前 是用 ” Save Tran tranName” 建立的 )  @@trancount值不变

否则,@trancount 减小1

注意:save tran 命令,不会使@@trancount加1

分析:
只要提交或者回滚事务后,程序内部改变了事务参数@@TRANCOUNT,就会出上述的错误,无一例外。

试图直接用Sql ”  set @@trancount = 1;”,这是SQLServer 不允许做的。

各位,出现上面的错误,最多的可能是在嵌套事务中。

 

如果不嵌套:没有begin tran前,@@trancount为0;  begin tran后,@@trancount  此时为1;完事后就commit或rollback,@@trancount  此时为0;--不般我们是写不错的。

嵌套呢:

看看我之前写的一个存储过程:

 

declare @trancount int –commit,rollback只控制本存储过程
set @trancount = @@trancount;

if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/
begin tran current_tran–当前事务点,rollback、commit都从这里开始
else
save tran current_tran
…….

….做事去了

…….

 

if @error_code != 0 or @logErrorCode != 1
begin
rollback tran current_tran
set @error_code = -1; — 失败
end
else
begin
commit tran current_tran
set @error_code = 1; — 成功
end
有没有问题?(current_tran是保存点哈,不明白的,后面有比较详细的介绍)

我用了好久了(在一个项目里面),可是突然有一天,也就是今天,它出事了。原因嘛,虽然写的是嵌套的,之前都没有嵌套调到过。

我在外围开了一个事务,再来调这个存储过程,当它 commit tran current_tran 时(rollback tran current_tran是不会有事的),会出什么错误?如果你不能很明确的告诉我,说明你还没有理解得深刻。做个选择吧?

1.”…BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。”

2.”…BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

 

答案:【2】。

线索分析:我是在外部开了一个事务的,所以在未进入该存储过程以前@@trancount的值应该为1;进入时,save tran current_tran, @@trancount值没有变;完事的,执行commit tran current_tran,@@trancount的值应该为0;--所以,进入前,出来后,@@trancount值发生了改变,SQLServer不干了(原因,自己去想吧:拆散了begin tran 配对)。

怎么解决:

1.进入子事务前先记录@@trancount,我们用变量@trancount来记录。

2. 提交子事务前,先判断之前的@trancount是否为0;为0表示”该事务”前没有事务调用,可以直接提交事务;不为0,表明进入该事务前已经有一个事务,该事务是子事务,不能提交。

— 如果当前计数为0,则提交.
— 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0),
— 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran)
if(@trancount = 0)
begin
commit tran current_tran
end
set @error_code = 1; — 成功

SqlServer 事务相关:《嵌套事务(一):.NET中嵌套事务运用的一点思考》

《嵌套事务(二):SqlServer中嵌套事务使用》

《SqlServer 嵌套事务机制 测试 》
————————————————
版权声明:本文为CSDN博主「xiaoyong322」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dfyong/article/details/6546138

Sqlserver——异常总结——详解嵌套事务中EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配发生的原因及处理方法_qq_40205468的博客-CSDN博客

mikel阅读(1686)

来源: Sqlserver——异常总结——详解嵌套事务中EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配发生的原因及处理方法_qq_40205468的博客-CSDN博客

下面是测试表和存储过程的代码

—创建测试表

IF EXISTS ( SELECT * FROM sys.tables WHERE name = ‘tt’ )
DROP TABLE dbo.tt ;

CREATE TABLE dbo.tt ( ID INT IDENTITY , Name NVARCHAR (100), TransCount INT ) ;
GO

—创建主存储过程
IF EXISTS ( SELECT * FROM sys.procedures WHERE name = ‘P_proc’ )
DROP PROC P_proc ;
GO

CREATE PROC P_proc
AS
BEGIN
BEGIN TRAN ;

INSERT INTO dbo.tt ( Name, TransCount ) SELECT ‘查询1’, @@TRANCOUNT ;

EXEC dbo.S_proc ;

RETURN ;
END ;
GO

—创建子存储过程

IF EXISTS ( SELECT * FROM sys.procedures WHERE name = ‘S_proc’ )
DROP PROC S_proc ;
GO

CREATE PROC S_proc
AS
BEGIN
BEGIN TRAN ;

INSERT INTO dbo.tt ( Name, TransCount ) SELECT ‘查询2’, @@TRANCOUNT ;

ROLLBACK ;

RETURN ;
END ;
执行主存储过程P_proc

分析这个错误提示,可以发现,这个错误其实是由子存储过程报错报错抛出的,

调用S_proc之前的 事务层数是1 ,而执行之后的事务层数是0 所以系统抛出执行异常。

其中 提示 上一计数 = 1,当前计数 = 0。

当单独执行时子存储过程时,可以看到。

是没有任务问题的。

我们再做个测试,独立执行子存储过程之前 手动开启两个事务,执行结果

可以看到上一计数的值正好和 事务的开启层数相同。

可以得出结论:调用存储过程,会对执行前后事务的层数作判断(查询 @@TRANCOUNT 可以看到当前会话的事务层数),如果不相等时会错误  ‘EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 =X,当前计数 =X’

——————————————–下面介绍一种解决方法

看示例代码

——Sp避免嵌套调用异常,编写格式

CREATE PROC TestSp ( @ReturnValue INT OUTPUT )
AS
BEGIN
SET XACT_ABORT ON ;

SET NOCOUNT ON ;

–开启事务–
BEGIN TRANSACTION ;

–创建事务节点(节点名格式: TRANSACTION +节点顺序(1,2,3,4)+ ‘_’+ Sp名称 )
SAVE TRANSACTION TRANSACTION1_TestSp ;

—-业务逻辑代码
BEGIN
INSERT tt SELECT 1 ;

—–异常处理1(回滚指定到事务节点)
IF 1 = 0
BEGIN
SET @ReturnValue = -1 ;

ROLLBACK TRANSACTION TRANSACTION1_TestSp ;

COMMIT ;

RETURN ;
END ;

END ;

–无异常,提交事务
SET @ReturnValue = 1 ;

COMMIT ;

RETURN ;
END ;
上面用到了一个SQL server的特性 :事务节点。

并以上述为例,讲述其用法和含义:存储过程中开启事务(@@TranCount=1),同时创建一个事务节点 TRANSACTION1_TestSp,当执行业务代码时:发生异常,并进行异常处理时,将回滚事务节点(而非回滚事务),将节点范围内的所有事务日志全部回滚(回滚之后的事务层数没有变化,@@TranCount未变化,仍然未1,只是回滚了事务日志),之后进行正常的提交,@@TranCount的层数-1;未发生异常时,正常提交@@TranCount的层数-1。

可以看到,不管最终的执行结果是成功返回还是异常返回,结果都只会将@@TranCount-1,而不会回滚整个事务层,避免了嵌套事务中的‘EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配’问题。

————原创,纯手打,觉得对您有帮助的话,帮忙点个赞哦!
————————————————
版权声明:本文为CSDN博主「志向数据库架构师的初级DBA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40205468/article/details/100561823

C#中TransactionScope的使用方法和原理_weixin_34348805的博客-CSDN博客

mikel阅读(548)

来源: C#中TransactionScope的使用方法和原理_weixin_34348805的博客-CSDN博客

在.net 1.1的时代,还没有TransactionScope类,因此很多关于事务的处理,都交给了SQLTransaction和SQLConnection,每个Transaction是基于每个Connection的。这种设计对于跨越多个程序集或者多个方法的事务行为来说,不是非常好,需要把事务和数据库连接作为参数传入。

在.net 2.0后,TransactionScope类的出现,大大的简化了事务的设计。示例代码如下:

static void Main(string[] args)
{
using (TransactionScope ts = new TransactionScope())
{
userBLL u = new userBLL();
TeacherBLL t = new TeacherBLL();
u.ADD();
t.ADD();
ts.Complete();
}
}
只需要把需要事务包裹的逻辑块写在using (TransactionScope ts = new TransactionScope())中就可以了。从这种写法可以看出,TransactionScope实现了IDispose接口。除非显示调用ts.Complete()方法。否则,系统不会自动提交这个事务。如果在代码运行退出这个block后,还未调用Complete(),那么事务自动回滚了。在这个事务块中,u.ADD()方法和t.ADD()方法内部都没有用到任何事务类。

TransactionScope是基于当前线程的,在当前线程中,调用Transaction.Current方法可以看到当前事务的信息。具体关于TransactionScope的使用方法,已经它的成员方法和属性,可以查看MSDN。

TransactionScope类是可以嵌套使用,如果要嵌套使用,需要在嵌套事务块中指定TransactionScopeOption参数。默认的这个参数为Required。

该参数的具体含义可以参考http://msdn.microsoft.com/zh-cn/library/system.transactions.transactionscopeoption(v=vs.80).aspx

比如下面代码:

static void Main(string[] args)
{
using (TransactionScope ts = new TransactionScope())
{
Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier);
userBLL u = new userBLL();
TeacherBLL t = new TeacherBLL();
u.ADD();
using (TransactionScope ts2 = new TransactionScope(TransactionScopeOption.Required))
{
Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier);
t.ADD();
ts2.Complete();
}
ts.Complete();
}
}
当嵌套类的TransactionScope的TransactionScopeOption为Required的时候,则可以看到如下结果,他们的事务的ID都是同一个。并且,只有当2个TransactionScope都complete的时候才能算真正成功。

如果把TransactionScopeOption设为RequiresNew,则嵌套的事务块和外层的事务块各自独立,互不影响。

static void Main(string[] args)
{
using (TransactionScope ts = new TransactionScope())
{
Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier);
userBLL u = new userBLL();
TeacherBLL t = new TeacherBLL();
u.ADD();
using (TransactionScope ts2 = new TransactionScope(TransactionScopeOption.RequiresNew))
{
Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier);
t.ADD();
ts2.Complete();
}
ts.Complete();
}
}

可以看到,他们的事务id是不一样的。

TransactionScopeOption设为Suppress则为取消当前区块的事务,一般很少使用。

对于多个不同服务器之间的数据库操作,TransactionScope依赖DTC(Distributed Transaction Coordinator)服务完成事务一致性。

但是对于单一服务器数据,TransactionScope的机制则比较复杂。主要用的的是线程静态特性。线程静态特性ThreadStaticAttribute让CLR知道,它标记的静态字段的存取是依赖当前线程,而独立于其他线程的。既然存储在线程静态字段中的数据只对存储该数据的同一线程中所运行的代码可见,那么,可使用此类字段将其他数据从一个方法传递到该第一个方法所调用的其他方法,而且完全不用担心其他线程会破坏它的工作。TransactionScope 会将当前的 Transaction 存储到线程静态字段中。当稍后实例化 SQLCommand 时(在此 TransactionScope 从线程局部存储中删除之前),该 SqlCommand 会检查线程静态字段以查找现有 Transaction,如果存在则列入该 Transaction 中。通过这种方式,TransactionScope 和 SqlCommand 能够协同工作,从而开发人员不必将 Transaction 显示传递给 SqlCommand 对象。实际上,TransactionScope 和 SqlCommand 所使用的机制非常复杂。具体可以参考文章http://www.microsoft.com/china/MSDN/library/netFramework/netframework/NETMattersSep.mspx?mfr=true

Wrox出版的《Professional C# 4 and .NET 4》也有关于TransactionScope的一些使用方法的介绍。
————————————————
版权声明:本文为CSDN博主「weixin_34348805」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_34348805/article/details/85099004

根据浏览器屏幕分辨率不同使用不同的css样式——响应式 - 叫我小谷 - 博客园

mikel阅读(783)

来源: 根据浏览器屏幕分辨率不同使用不同的css样式——响应式 – 叫我小谷 – 博客园

根据浏览器屏幕分辨率不同使用不同的css样式

有两种方法实现:1、用css的@media(原生写法);2、利用bootstrap的网格系统。(个人推荐用第二种方法。)

一、使用纯css实现

语法:@media only screen and (判断属性) {css样式}

理解:判断属性有:1、(min-width: 1200px)——不小于1200px;2、(max-width: 1200px)——不大于1200px;3、(min-width: 800px) and (max-width: 1200px)——不小于800px且不大于1200px。

下面写个简单的例子:

1、建一个class为content的div层,并引入css文件。

<head>
<meta charset=”UTF-8″>
<title>根据屏幕分辨率不同使用不同的css样式</title>
<link rel=”stylesheet” type=”text/css” href=”css/pingmu.css”/>
</head>
<body>
<div class=”content”>
<p>divcss3我这个层会根据浏览器屏幕分辨率不同显示不同的样式哦</p>
</div>
</body>

2、写css样式。

.content{
margin: 0px auto;    /*使content层居中*/
}
@media only screen and (min-width: 1200px) {
/*    设置了浏览器宽度不小于1200px时,content显示1200px的宽度样式    */
.content{
width: 1200px;
height: 600px;
background-color: #369;

}
}
@media only screen and (min-width: 800px) and (max-width: 1199px) {
/*    设置了浏览器宽度不小于800px且不大于1199px时,content显示1000px的宽度样式    */
.content{
width: 1000px;
height: 600px;
border: solid 2px #F50000;
}
}
/**
* 注意分辨率区间的分配,如上面的1199px,若改为1200px,则在屏幕宽度位1200px时,content将运用两个样式。
*/
@media only screen and (min-width: 500px) and (max-width: 799px) {
/*    设置了浏览器宽度不小于500px且不大于799px时,content显示650px的宽度样式    */
.content{
width: 650px;
height: 600px;
color: #f50000;
background-color: #999;
}
}
@media only screen and (max-width: 499px) {
/*    设置了浏览器宽度不大于499px时,content显示200px的宽度样式    */
.content{
width: 200px;
height: 200px;
font-size: 15pt;
border: dashed 1px #666;
}
}

二、使用bootstrap(css框架)实现

例子如下:

<head>
<meta charset=”UTF-8″>
<!–移动端的响应式写法:加下面语句–>
<!–<meta name=”viewport” content=”width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no” />–>
<title></title>
<link rel=”stylesheet” type=”text/css” href=”css/bootstrap.min.css” />
<style type=”text/css”>
.content {
margin: auto;
width: 1000px;
height: 600px;
background-color: #ccc;
}

/**
* .col-sm-6 就是当屏幕总宽度在750px~970px区间中时,把显示内容的框平均分为两列
* 此为bootstrap的网格系统。
*/
.col-sm-6{
height: 250px;
}
.c1{
background-color: #f50000;
}
.c2{
background-color: #333;
}
.c3{
background-color: #666;
}
.c4{
background-color: #aaa;
}

</style>
</head>

<body>
<div class=”content”>
<div class=”yiceng”>
<!–根据浏览器屏幕分辨率不同使用不同的css样式——bootstrap方法–>
<div class=”col-sm-6 col-md-3 c1″></div>
<div class=”col-sm-6 col-md-3 c2″></div>
<div class=”col-sm-6 col-md-3 c3″></div>
<div class=”col-sm-6 col-md-3 c4″></div>
</div>
</div>
</body>

 

bootstrap的网格系统理解:bootstrap把网页均分为12份,我们可以根据自己的需要自行分配每列内容显示所占的份额(如3列的分法有:1-9-1、2-8-2、3-6-3、4-4-4等)。此外,class前缀有四种:1、.col-xs-(代表:屏幕大小<=768px,此时可显示内容的最大区域自动);2、.col-sm-(代表:768px<=屏幕大小<=992px,此时可显示内容的区域最大为750px);3、.col-md-(代表:992px<=屏幕大小<=1200px,此时可显示内容的区域为970px);4、.col-lg-(代表:屏幕大小>=1200px,此时可显示内容的区域最大为1170px)。四种网格系统可以联合使用。

 

三、移动端的响应式:

在<head>标签中导入bootstrap的css框架包,然后输入下面语句(语法结构如下):

<meta name=”viewport” content=”width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no” />

理解:设置 meta 属性为 user-scalable=no 可以禁用移动端的缩放(zooming)功能;initial-scale——最初比例;minimum-scale——最小比例;maximum-scale——最大比例。此处时1:1:1,你也可以根据需要自行设置。

这样,在PC端设置的css样式在移动端也时一样的效果,不会因为移动端的屏幕变小而使内容缩小。

CSS媒体查询,CSS根据不同的分辨率显示不同的样式 - 鱼塘总裁 - 博客园

mikel阅读(867)

来源: CSS媒体查询,CSS根据不同的分辨率显示不同的样式 – 鱼塘总裁 – 博客园

在写响应式网页的时候,我们需要网页有几种显示方式,我们可以用CSS实现这个功能

使用CSS提供的媒体查询,我们可以根据屏幕分辨率来使用相应的CSS样式

1
2
3
4
5
6
7
8
9
@media screen and (max-width1000px) {
/*此条件表示最大宽度为1000,也就是如果宽度小于1000则执行以下CSS代码*/
#idming{
    color:#f00;
}
.leiming{
    color:#f66;
}
}

 

已知国内量化平台 - 廖贵宾 - 博客园

mikel阅读(1186)

来源: 已知国内量化平台 – 廖贵宾 – 博客园

盈时

成立时间:2016.06
服务:
1.选取参数,自动生成策略(需要购买次数)
2.购买别人的策略
语言:   Python
目标客户:   期货投资者(有无编程基础都可)
数据库:   期货
回测用时:   需要排队分钟记
支持的功能:   支持将策略使用在交易开拓者的平台,属于实盘交易。策略给出建议,但需要自己手动确定进行买卖。
优势:
1.对期货做策略(竞争少)
2.运用机器学习,理论更新颖
3.能够自己代入实盘
自动生成策略原理与简介:   通过设置参数,然后通过机器学习的方法,判断期货应该如何交易才能盈利。
备注:国内首个利用深度学习的人工智能量化平台

聚宽

成立时间:   2015.05
服务:
1.选取参数,自动生成策略
2.可以自己编写代码,生成策略(有代码显示)
语言:   Python, R
目标客户:   有经验的quant
数据库:   全面
回测用时:   分钟记(动图的形式)
支持的功能:
1.支持日级、分钟级回测
2.支持日级、分钟级、tick级模拟交易
3.免费提供A股行情、财务数据、指数数据、基金数据
优势:
1.期货,期权有数据,但得自己做
2. 支持回测中访问网络
3.社区活跃,有很多不错的ETF策略
4.有销售策略活动
5.Api丰富且友好
自动生成策略原理与简介:   通过设置的参数,不断筛选股票池里的股票,然后根据市场变动,判断是否进行操作。(打分法)
备注:
1. 门槛低,人人皆可为宽客
2. 可设置股票是否复权

优矿

成立时间:   2015.10
服务:   可以自己编写代码,生成策略(有代码显示)
语言:   Python
目标客户:   刚入门的quant,有编程基础
数据库:   全面
回测用时:   以秒记(动图的形式)
支持的功能:
1.IPython Notebook与回测引擎的整合可做参数优化
2.支持分钟线回测及日数据仿真交易
3.CAL库支持了不少常用的不常用的金融算法
4.可自定义library,复用自己的模块
优势:
1.数据全面
2.有比赛可以进行交流
3.有适用于高频交易的专业版
备注:   比赛的形式还是挺吸引人的

Ricequant

成立时间:   2014.12
服务:   需要自己编写代码生成策略
语言:   Python,Java
目标客户:   有经验的quant
数据库:   A股(2005年至今)
回测用时:   分钟回测
支持的功能:
1.针对 FOF 投资的 CRM 功能
2.支持用户分组
3.自动邮件提醒
4.数据更新选项
优势:
1.使用RQBeta回测绩效分析,结果展示丰富
2.视觉设计和文档做的非常棒,特别是回测结果页面,看着很舒服
3.定期举办比赛

BigQuant

成立时间:   2016.04
服务:   选取参数,自动生成策略(使用机器学习,并配有代码)
语言:   Python
目标客户:   一般股民
数据库:   A股
回测用时:   十分钟
支持的功能:
1.因子可供选择得很多
2.有基础知识教程
优势:
1.可供选择的因子多
2.门槛低
自动生成策略原理与简介:   选取参数后,使用历史数据,利用机器学习的原理考虑是否进行交易,在实盘时,用实盘日期,回测时用传入的数据。(机器学习)

镭矿

成立时间:   2015.04
服务:
1.选取参数,自动生成策略
2.可以自己编写代码,生成策略
语言:   Java、Python
目标客户:   一般股民
数据库:   A股(2012至今)
回测用时:   以秒记
支持的功能:   回测速度快
优势:
1.回测速度快
2.可以使用Java
自动生成策略原理与简介:   选取参数后,不断筛选股票,然后根据实际价格变动,判断是否进行操作。(打分法)
备注:   基础知识介绍偏少,但有相关代码介绍,有长短期的区别

果仁网

成立时间:   2015.08
服务:   选取参数,自动生成策略(没有代码)
语言:   未知
目标客户:   一般投资者
数据库:   国内上市的A股和ETF
回测用时:   以秒记
支持的功能:   考虑对冲(vip)
优势:
1.因子选择界面感觉最舒服
2.回测快
3.将对冲考虑在内
自动生成策略原理与简介:   选取因子后,筛选出股票然后排名。一种是在每个交易日结束时卖出,然后买入想要的股票;另一种是卖出不符合的股票,买入合适的股票。(打分法)
备注:   界面用起来挺舒服,有长短期的区别

京东量化

服务:
1.选取参数,自动生成策略
2.可以自己编写代码,生成策略(有代码显示)
语言:   Python(Java还不能用)
目标客户:   一般投资者
数据库:   指数数据、京东大数据
回测用时:   以秒记、以动图的形式体现
支持的功能:   提供量化选股服务
优势:
1.回测速度快
2.可以量化选股
自动生成策略原理与简介:   选取因子后,筛选出股票。然后根据之前的数据,和今日实时更新的数据,判断如何对股票进行操作。(打分法)
备注:   无长短期分别,但有调仓周期

Factors

成立时间:   2016.11
服务:   选取因子,自动生成策略 。
语言:   未知
目标客户:   一般股民
数据库:   A股
回测用时:   无法回测
优势:
1.无需编程,自动生成策略。
2.综合运用多因子构建模型对股票进行评价
自动生成策略原理与简介:   选取因子后,筛选出股票。然后根据实时数据,判断是否交易。(打分法)

掘金 

成立时间:   2015.01
服务:   选取策略模版,手动编程
语言:   C/C++、C#、MATLAB、Python、R
目标客户:   投资者、策略提供者
数据库:   全面
回测用时:   首次回测秒级完成,后续回测毫秒级完成
支持的功能:
1.统一的量化交易接口
2.一致的策略事件模型
3.完善的风险控制机制
4.多策略多账户支持
5.完整的策略生命周期管理
优势:
1.策略存放在本地,安全性高
2.可定制性强
3.定期举行比赛
备注:   支持tick数据

微量网

成立时间:   2014.01
服务:   选取参数,自动生成策略(没有代码)
语言:   未知
目标客户:   一般投资者
数据库:   全面
支持的功能:   期货程序化CTA策略
优势:   有策略从上传到出售全流程链   自动生成策略原理与简介:   选取因子后,筛选出股票。然后根据实时数据,判断是否交易。(打分法)
备注:   国内首家采用策略云托管模式的投资平台

众量网

成立时间:   2014.01
服务:选取参数,自动生成策略(没有代码)
语言:   未知
目标客户:   一般投资者
数据库:   全面
回测用时:   以秒记
支持的功能:   通过众包做量化投资策略,全视角,跨品种,多周期,无编程
优势:
1.品种多样化
2.效率高
自动生成策略原理与简介:   建立一个建仓条件,一个出仓条件,可以设置止损和分批建仓次序。然后看盈利多少(按行业分)
备注:   个人感觉做得太过粗糙

云量科技

成立时间:   2015.11
服务:选择策略及交易账户层面的风控模块(即刻使用)
语言:   未知
目标客户:   投资者、策略提供者
数据库:   全面
回测用时:   以秒记
支持的功能:   量化投资策略开发、交易算法设计、投资咨询、移动互联网(投资类)应用开发
优势:
1.高模仿人类对话
2.超智能营销多维度精确锁定,主动出击唤醒
3.全网覆盖、7*24小时服务
备注:   是一个公司,提供机器人服务,不是量化投资平台

诸葛量化

成立时间:   2016.12
服务:选取参数,自动生成策略(没有代码)
语言:   Lua   目标客户:   投资者、策略提供者
数据库:   A股
回测用时:   以秒记
支持的功能:   策略生成 ,策略购买;资产配置 ,条件选股
优势:
1. 快速生成策略
2. 自带遗传基因算法,智能优化策略
自动生成策略原理与简介:   选股方法有两种:打分法,趋势法(今日比昨日打分高就买进)。然后通过遗传算法改进策略,达到满意为止(有遗传代数限制),最终接入实盘。

量化大师(软件)

成立时间:   2013.08
服务:选取参数,自动生成策略(没有代码)
语言:   未知
目标客户:   一般投资者(散户)
数据库:   A股
支持的功能:   量化选股、策略回溯、策略提醒、程序化交易
优势:   效率高
自动生成策略原理与简介:   选取因子后,根据实时股价进行筛选,选出排名靠前的股票(个数自己设置),然后根据实时数据,判断是否交易。(打分法)
备注:   一款手机app

况客

成立时间:   2014.12
服务:   提交数据,生成图表,检验信息的准确性
语言:   R
目标客户:   投资者、策略提供者
数据库:   A股
支持的功能:   针对 FOF 投资的 CRM 功能,支持用户分组,自动邮件提醒,数据更新选项
优势:
1.量化策略可根据用户需求灵活定制
2.操作简单
3.交易策略评估清晰明确
4.工具免费化
5.可网络调度
备注:   是对你手上已有数据的一个可视化处理,让数据看起来更加形象。

MindGo

成立时间:   2017.02注册商标
服务:   需要自己编写代码生成策略
语言:   Python
目标客户:   投资者、策略提供者
数据库:   A股
回测用时:   以秒记
支持的功能:   数据研究、策略回测、模拟交易、自然语言选股/回测
优势:
1. 数据齐全
2. 支持tick回测
3.支持自然语言回测
4.定期举行比赛

BotVS

成立时间:   2015.07
服务:需要自己编写代码生成策略
语言:   JavaScript、Python、云端编写
目标客户:   投资者、策略提供者
数据库:   全面
回测用时:   以秒记
支持的功能:   回测、实盘模拟交易、实盘接入交易
优势:
1.模块化策略开发
2.策略分享机制
3.P2P模式策略租用机制
4.实盘公开展示
5.支持三大金融市场

DigQuant(点宽)

成立时间:   2004年
服务:   需要自己编写代码生成策略
语言:   MATLAB
目标客户:   投资者、策略提供者
数据库:   全面
回测用时:   以秒记
支持的功能:
1.基于 MATLAB 的量化策略
2.支持股票、期货的策略研究和程序化交易(是一个软件Auto-Trader Pro)
3.量化研究文章分析
优势:
1.其核心架构与微软 Azure 云架构深度整合
2.社区内有《中国证券期货》杂志专栏
备注:
1.基于 MATLAB 的量化策略
2.核心产品主要是巴别塔实时协作平台系列软件产品

OpenQuant

成立时间:   1997年
服务:   需要自己编写代码生成策略
语言:   C#
目标客户:   能提供投资方案的投资策略编写者
数据库:   全面
支持的功能:   交易策略创建开发、策略回测、参数优化、策略运行及风险监控。
优势:
1.可构建大型对冲基金级量化交易解决方案
2.专业用户可扩展全新功能
3.丰富的金融函数及专业软件对接能力

中量网-交易王

成立时间:   2012年
数据库:   全面
支持的功能:   中量金融、中量股票、期货仿真、期货实盘、策略商城

i量化

成立时间:   2015.01
数据库:   全面
支持的功能:   量化交易、金融咨询、社交、在线教育
优势:
1.拥有海外量化投资最专业的平台
2.提供开放的社区和在线教育服务
quantopian

服务:   可以自己编写代码,生成策略(有代码显示)
语言:   Python
数据库:   US equities futures(最早2002)
回测用时:   分钟记(动图的形式)
支持的功能:   回测、实盘模拟交易、实盘接入交易
优势:   能够借助他人做实验检测

quantconnect

服务:   可以自己编写代码,生成策略(有代码显示)
语言:   C#、F#、Python
目标客户:   engineer
数据库:   股票 外汇 基金 期权 期货(US)
回测用时:   分钟记(动图的形式)
支持的功能:   回测、实盘模拟交易、实盘接入交易
优势:
1.可以很方便地将自己的策略应用到实际中
2. lean(Lean Algorithmic Trading Engine)基于C#的算法交易平台的运用和介绍

quantstar

服务:   Qstrader的引入
语言:   Python
支持的功能:   回测、实盘模拟交易、实盘接入交易
优势:   有3本书籍介绍

zulutrade

服务:
1.你可以成为交易者(提供策略)
2.你可以跟随他人的策略
3.策略基于外汇,二元期权
语言:   Java
目标客户:   一般金融爱好者、engineer
数据库:   外汇、二元期权
支持的功能:   外汇策略交易
优势:   专门做外汇方面的

quantbedia

服务:   搜索合适的策略使用,编写策略上传
语言:   Python
数据库:   几乎所有的数据都有
优势:   一个很明显的策略交易平台

algotrading101

服务:   讲解机器学习应用到策略中(主要是教学)
优势:   运用了机器学习

investopedia

服务:   股票,外汇模拟交易(教学)
数据库:   股票  外汇
优势:   教导新手做相关模拟交易

Amibroker

服务:   一个系统化交易的平台
语言:   formula language
数据库:   股票  外汇
优势:   比较全面,功能齐全,速度快

Chrome 错误代码:ERR_UNSAFE_PORT_chrome,错误代码,ERR_UNSAFE_PORT_无知人生,记录点滴-CSDN博客

mikel阅读(901)

来源: Chrome 错误代码:ERR_UNSAFE_PORT_chrome,错误代码,ERR_UNSAFE_PORT_无知人生,记录点滴-CSDN博客

最近在用Nginx发布多个站点测试,使用了87、88端口,

88端口访问正常,87端口就怎么也访问不了,

点击更多,提示错误代码:ERR_UNSAFE_PORT

不安全的端口?尼玛就只靠端口就能解决不安全问题了?

不想修改浏览器设置的就改用其它端口吧,搜索了一下,Firefox也有类似的端口限制;如果非要使用类似的端口,

我们要做的是允许访问非常规端口地址,解决办法:选中Google Chrome 快捷方式,右键属性,在”目标”对应文本框添加:

–explicitly-allowed-ports=87,6666,556,6667

允许多个端口以逗号隔开,最终如下:

C:\Users\Huoqing\AppData\Local\Google\Chrome\Application\chrome.exe –explicitly-allowed-ports=6666,556
附录:Google Chrome 默认非安全端口列表,虽然以上方法可以解决问题,但建议尽量避免以下端口:

1, // tcpmux
7, // echo
9, // discard
11, // systat
13, // daytime
15, // netstat
17, // qotd
19, // chargen
20, // ftp data
21, // ftp access
22, // ssh
23, // telnet
25, // smtp
37, // time
42, // name
43, // nicname
53, // domain
77, // priv-rjs
79, // finger
87, // ttylink
95, // supdup
101, // hostriame
102, // iso-tsap
103, // gppitnp
104, // acr-nema
109, // pop2
110, // pop3
111, // sunrpc
113, // auth
115, // sftp
117, // uucp-path
119, // nntp
123, // NTP
135, // loc-srv /epmap
139, // netbios
143, // imap2
179, // BGP
389, // ldap
465, // smtp+ssl
512, // print / exec
513, // login
514, // shell
515, // printer
526, // tempo
530, // courier
531, // chat
532, // netnews
540, // uucp
556, // remotefs
563, // nntp+ssl
587, // stmp?
601, // ??
636, // ldap+ssl
993, // ldap+ssl
995, // pop3+ssl
2049, // nfs
3659, // apple-sasl / PasswordServer
4045, // lockd
6000, // X11
6665, // Alternate IRC [Apple addition]
6666, // Alternate IRC [Apple addition]
6667, // Standard IRC [Apple addition]
6668, // Alternate IRC [Apple addition]
6669, // Alternate IRC [Apple addition]
————————————————
版权声明:本文为CSDN博主「微wx笑」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/testcs_dn/article/details/39186225