|
@@ -0,0 +1,115 @@
|
|
1
|
+安装
|
|
2
|
+```
|
|
3
|
+Install-Package Maikebing.Data.Taos
|
|
4
|
+```
|
|
5
|
+
|
|
6
|
+使用
|
|
7
|
+```
|
|
8
|
+string database = "db_" + DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
9
|
+
|
|
10
|
+//配置文件
|
|
11
|
+var builder = new TaosConnnectionStringBuilder()
|
|
12
|
+{
|
|
13
|
+ DataSource="rest/sql",
|
|
14
|
+ DataBase = database,
|
|
15
|
+ Username="",
|
|
16
|
+ Password=""
|
|
17
|
+};
|
|
18
|
+
|
|
19
|
+//创建上下文
|
|
20
|
+using(var context = new TaosContext(new DbContextOptionsBuilder().UseTaos(builder.ConnectionString).Options))
|
|
21
|
+{
|
|
22
|
+ context.Database.EnsureCreated();
|
|
23
|
+ context.sensor.Add(new sensor(){ts = DateTime.Now.AddMillieseconds(i), degree=rd.NextDouble(), pm25=rd.Next(0,1000)});
|
|
24
|
+ context.SaveChanges();
|
|
25
|
+}
|
|
26
|
+```
|
|
27
|
+
|
|
28
|
+# 理解
|
|
29
|
+
|
|
30
|
+把所有的配置包裹在一个类中,是常规做法,这里就是`TaosConnectionStringBuilder`,它继承了`DbConnectionStringBuilder`,而`DbConnectionStringBuilder`是`System.Data.Common`中的一员。
|
|
31
|
+
|
|
32
|
+`System.Data.Common`这个命名空间的主要负责DataSet和DataSource之间的操作,无非是读和写。TDengine的 .NET Core连接器就是利用了该命名空间的工作机制完成了数据的读写,是一种非常成熟的做法,这种成熟建立在该命名空间内在机制的成熟。
|
|
33
|
+
|
|
34
|
+`System.Data.Common`主要包含了以下几个类:
|
|
35
|
+
|
|
36
|
+- DbConnectionStringBuilder: 专门用来处理连接字符串
|
|
37
|
+- DbConnection:DataSet和DataSource之间的连接
|
|
38
|
+- DbCommand:可以理解为sql语句或者存储过程
|
|
39
|
+- DbParameter和DbParameterCollection:理解成DbCommand所需要的参数
|
|
40
|
+- DbDataReader:负责从DataSource中读取数据。
|
|
41
|
+- DbTransaction:可能是DbDataReader和DbCommand的封装
|
|
42
|
+
|
|
43
|
+**通过`TaosConnectionStringBuilder`传入的参数是如何被内在机制接受的呢**?
|
|
44
|
+
|
|
45
|
+通过属性赋值进来。内部对属性如何处理呢?原来,不仅交给了基类,也交给了本类的字段。
|
|
46
|
+```
|
|
47
|
+public class TaosConnectionStringBuilder : DbConnectionStringBuilder
|
|
48
|
+{
|
|
49
|
+ //virutal意味着必须有方法体,abstract不能有方法体
|
|
50
|
+ //virutal可以不被子类重写,但如果子类要重写必须加上override
|
|
51
|
+ //abstract方法必须被子类重写
|
|
52
|
+ public virutal string Username
|
|
53
|
+ {
|
|
54
|
+ get {return _userName;}
|
|
55
|
+ set {
|
|
56
|
+ base[UserNameKeyword] = _userName = value;
|
|
57
|
+ }
|
|
58
|
+ }
|
|
59
|
+}
|
|
60
|
+
|
|
61
|
+```
|
|
62
|
+
|
|
63
|
+`TaosConnectionStringBuilder`还有一处设计很巧妙,就是通过一个静态构造函数把一个内部的枚举分别放在了只读List类型和Diction类型的集合中去了,分别是`IReadOnlyList<string>`和`IReadOnlyDictioanry<string, Keywords>`。静态构造函数什么时候会调用呢?就是类在第一次实例化或者访问类的静态成员的时候调用。
|
|
64
|
+```
|
|
65
|
+public class TaosConnectionStringBuilder : DbConnectionStringBuilder
|
|
66
|
+{
|
|
67
|
+ static TasoConnectionStringBuilder()
|
|
68
|
+ {
|
|
69
|
+
|
|
70
|
+ }
|
|
71
|
+
|
|
72
|
+ //virutal意味着必须有方法体,abstract不能有方法体
|
|
73
|
+ //virutal可以不被子类重写,但如果子类要重写必须加上override
|
|
74
|
+ //abstract方法必须被子类重写
|
|
75
|
+ public virutal string Username
|
|
76
|
+ {
|
|
77
|
+ get {return _userName;}
|
|
78
|
+ set {
|
|
79
|
+ base[UserNameKeyword] = _userName = value;
|
|
80
|
+ }
|
|
81
|
+ }
|
|
82
|
+}
|
|
83
|
+
|
|
84
|
+```
|
|
85
|
+
|
|
86
|
+这个连接器令人叹为观止的一点是还使用了`DbContext`的内在机制针对时序数据库有了上下文,这是如何做到的呢?
|
|
87
|
+
|
|
88
|
+--基本上扩展了`Entity Framework Core`的所有方面。
|
|
89
|
+
|
|
90
|
+# 扩展`IDesignTimeDbContextFactroy`
|
|
91
|
+
|
|
92
|
+这个接口用来定义在设计时,比如生成迁移文件的时候如何设置上下文。
|
|
93
|
+```
|
|
94
|
+public class SampleContextFactory : IDesignTimeDbContextFactory<SampleContext>
|
|
95
|
+{
|
|
96
|
+ public SampleContext CreateDbContext(string[] args)
|
|
97
|
+ {
|
|
98
|
+ var optionsBuilder = new DbContextOptionsBuilder<SampleContext>();
|
|
99
|
+ optionsBuilder.UseSqlServer("",opts => opts.CommandTimeout((int)TimeSpan.FromMinutes(10).TotalSeconds));
|
|
100
|
+
|
|
101
|
+ return new SampleContext(optionsBuilder.Options);
|
|
102
|
+ }
|
|
103
|
+
|
|
104
|
+}
|
|
105
|
+```
|
|
106
|
+
|
|
107
|
+上下文一定
|
|
108
|
+```
|
|
109
|
+public SampleContext(DbContextOptions options) : base(options){}
|
|
110
|
+```
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|