收到一位网友私信说在XJ,没办法上Git,建议改到Gitee,我接受了@学方说 网友的建议:
一是我自己上Git速度也不稳定经常遇到无法推送的情况,有时需要FQ才行,相信很多网友也是如此;
二是软件本身就是头条教程上的配套,基本上都是国内用户,确实没必要放到国外网站;
所以从本节开始,代码就都更新到Gitee上了,GitHub上的停止更新。鉴于Gitee上代码的流畅访问,代码看起来也很方便,功能也很多,如下图:
一键复制,编辑等等都有了,功能还是很不错的,最主要的是速度很快!再次感谢 @学方说 的建议。
所以本节教程开始,代码我就不全部贴在头条上了,大篇的代码影响文章阅读。哪里有新的知识点我再贴哪,重点讲解。另外建议大家在电脑上看教程和代码,手机浏览和娱乐还可以,真正想实践还得是电脑。Gitee的地址大家可以通过私信获取,教程下面有方法。
看了上节内容网友评论,还需要再多说几句:
一是有人说项目代码冗余。我承认我写的代码是可以精简的,但我要强调一点:写代码不要过分追求精简,这种想法本身就是错误的!做软件产品不是编程比赛,这是一个长期且漫长的过程,有些软件产品的生存周期可以到10年以上,我现在已经有一个软件产品已经有8年了,还在继续发挥余热。在满足功能的条件下,代码越容易理解和维护才是最好的代码。有些人根本没有这些项目和产品的经验,学到一点技术就觉得自己掌握了全部,能用Lamda的坚决不写函数体,殊不知一很难复用,二影响日后阅读,三不方便调试。为了精简而精简,实在大可不必。
二是说到ORM。上节我已经解释过为什么不用ORM,可是仍然还有两个人在说用sqlsugar,我觉得有必要再解释下,因为这其实是一个战略问题。大家既然跟我学做产品,有些东西我必须要讲明。首先我并没有用过sqlsugar,我到网上大概查了一下相关的资料与评价,还是不错的,但是我不选它有我的考虑:
(1)新手应该先学基础,如果你用数据库,连sql语句都不知道是什么,又怎能把程序做好;这种类库基本使用没问题,高级一点的查询要么需要很多方法的组合,要么根本无法实现,最终的解决方案还是要靠组装sql来完成,到头来还是要重新来过,倒不如一开始就从基础开始,循序渐进,等完全掌握后再学用轮子,那时才能游刃有余;
(2)对第三方类库的使用必须在可控范围内。我们的定位不是做项目,以最快速度做完交付完事,我们是要做产品,至少5年规划。凡是第三方的东西都是在原生基础上进行封装的,你必须使用他们的类库。用得越多,被绑架的代码就越多。如果哪一天你的项目到了百万行级的时候,你突然发现这个类库已经不再维护或迟迟没有适应新的系统或架构,再或是突然收费了,你这时想改才意识到项目中依赖的代码太多了,改可能会衍生出很多Bug;不改又可能面临巨大的风险,给自己搞得非常被动。如果你真想做一个长久的事业就一定要记住,控制权一定要牢牢掌握在自己的手里,别忘了美国人是怎么卡我们脖子的,你被别人卡脖子的地方越少,你被干掉的风险就越低。当然我这里也不是说大家所有第三方类库都不要用,要分情况:如果是解决某一个问题,比如文本编辑器,一个项目中也就是在一两个页面中会用到,如果哪天想替换改这两个页面的代码就好了,对产品本身不会造成影响,那就随便用了,这只是一个点,无伤大雅;像sqlsugar这种,本身没什么技术含量但代码中需要大量使用就尽量不要用了,这是一个面,弄不好会影响全局。如果实在有必要自己动手开发一个就好了,自己完全可控,何必把脖子主动送给别人呢?
以上说了这么多,就是希望同学们无论做什么,都要动脑思考,千万不可人云亦云。网上的很多人都自以为是,文章都看不全就一顿乱写,知道点皮毛就以为了解了整个世界。我们是一个软件产品的独立开发者,要有自己的定力,毕竟这是我们自己要奋斗终生的事业,不是键盘侠们打几个字就完事了的。
有点说多了,其实我好像更愿意说这方面的事,不用截图也不用录屏,省事些。
下面还是回到正题吧,继续Sqlite。
在第12节,sqlite入门的时候,我们在MainForm中实现了sqlite的连接测试,事实上,那只是我们的测试代码,这些不应该在UI项目中,而应该在BAL中,另外,我们需要对sqlite进行简单的封装,让它使用起来更加方便。
为此,我们需要在BAL中创建一个DBController的类,这个类专门用于sqlite的操作。
具体代码我已经放到了Gitee上,有兴趣的同学自行获取。
我收缩了一下代码,大概说下DBController的类
DAL项目中需要增加Microsoft.Data.Sqlite的引用,具体方法之前讲过,不重复了。
两个类变量:
关于sqlite的操作,我只讲query的函数,其余的就不逐一讲解了,大同小异:
public List<Hashtable> query(string sql){List<Hashtable> results = new List<Hashtable>();try{if (_conn == null) return results;SqliteCommand command = new SqliteCommand(sql, _conn);SqliteDataReader reader = command.ExecuteReader();while (reader.Read()){Hashtable values = _reader2hash(reader);results.Add(values);}return results;}catch (SqliteException ex){LastException = ex;return results;}}
这里我的返回值用了一个List<Hashtable>,List是一个数序列表,Hashtable则是c#中常用的哈希表类,最重要的特性就是可以通过键值直接获取数据,不用像List一样遍历获取,并且Hashtable中可以存取任何类型的值,特别适合数据库这种多样数据类型的字段。用List<Hashtable>这样的类型来承载多组的数据记录非常适合。当然同学们也可以用其他的如Tuple或者其他自定义类,可以自行尝试,我用这种方式熟练了,就不改了。
SqliteCommand command = new SqliteCommand(sql, _conn);SqliteDataReader reader = command.ExecuteReader();while (reader.Read()){Hashtable values = _reader2hash(reader);results.Add(values);}
这一段放在一起说,声明一个SqliteCommand实例,然后调用ExecuteReader获取SqliteDataReader的实例,然后循环读取,每读到一条数据就Hashtable,放到返回结果中,继续读取,直到全部读完。
逻辑很简单,需要说明的是基本上市面上常见的数据库操作都是这个套路,声明xxxCommand,然后执行就好了。大家也注意到了,所有数据库操作我都加了try...catch,因为数据库存取调用的都是外部设备(数据库文件),比较容易发生各种各样的问题,捕获信息后我们就可以根据具体情况进行处理了。后面会有章节专门来处理异常信息。
余下的函数和变量大概简略说一下,同学们自行理解,有不懂的可以评论区留言:
connectToDatabase就是通过文件路径连接数据库;
executeNoReturn是执行SQL,不返回任何结果;
executeHasReturn是执行SQL,返回执行的结果;
hasRecord是执行SQL,判断指定的sql能否返回记录;
query是查询sql,返回所有符合条件的记录;
query_first是查询sql,但仅返回第一条记录;
_reader2hash是私有函数,通过sqlite查询返回的内容是SqliteDataReader;
我都可以预想到,这篇文章如果有键盘侠看到,肯定又会挑这个DBController类的毛病了:
如果他们这样说,那也都是对的,因为上面这些问题都是我在以前的项目中实实在在遇到的,可以说上面任何一个点提出来,我也许都可以再写个几万字的专栏。但我为什么说他们都是键盘侠呢?因为他们只知道喷,都觉得自己比作者要NB,从来都不会认真思考作者为什么要这样写?任何事情都是由一个面的事,既然是面就等于深度*广度,很多人做不好事情,就是这两个方向的度掌握得不好,轻则隔靴挠痒,重则过犹不及。比如我现在写的这个系列文章是面向新手的,对新手来说基础最重要,所以上面那些我选择性不讲。我的目标很明确,通过做一个Winform项目实现C#的入门教学,功能持续推进,需要什么添什么,哪里不对改哪里。正所谓:咬定青山不放松,任尔东西南北风。
Sqlite封装好之后,我们就可以在此基础上对DAL.Category做接口集成了,如何来完成,我们下节继续。
----------------------------------------------------
本教程尽量保证2天一更,项目源码已作为开源项目加入到Gitee,代码内容会随教程实时更新,大家有兴趣的话可以关注我,以获得最及时的更新。私信:
私人日记 可以获取Gitee的链接;sqlitestudio可以获取sqlitestudio的链接;
C#基本语法大家在头条搜索“菜鸟c#”,个人感觉这个网站还可以。
大家阅读过程中有哪些看不懂或未尽兴的地方,可以在评论区留言,我会先记下来在后续的教程中找机会再说。
教程有帮助的话请大家帮忙关注、转发、扩散,能不能开专栏还需要你们的支持!