我们该如何设计数据库(三)(续)(2)

篇博客《我们该如何设计数据库(三)》写出来之后,深感自己写得不够清晰,虎头蛇尾,描述问题用了很多篇幅,而问题的解决方案及其优缺点却是一笔带过,于是就写下了这篇博客来负荆请罪。




这样做的优势在于:

1、使用了OO的思想来设计Model,更易于理解与后期维护。

对于查看类的继承关系,VS也提供了很好的支持,比如说你可以这样看:

我们该如何设计数据库(三)(续)(2)

你也可以这样看:

我们该如何设计数据库(三)(续)(2)

2、更清晰的关注点分离.

其实这个是Code First的好处,让程序员可以直接从Model写起,不必关注数据库中的表结构。

如果您对于使用ORM自生成数据库有疑问,请自行百度"Code First"和"数据迁徙"。也欢迎留言讨论。

这样做的缺点在于:

1、依赖ORM

2、违背开闭原则:要修改Namespace来切换Model(详情见下文) 想要切换Model,要修改一处地方(见下文),虽然修改很少,但还是让人不爽。

3、违背了第三范式:

如Contact,根据第三范式应该独立作为一个表,但是这里却是写入了Teacher表中。

也的确有无数人——朋友,同事,网友——吐槽过我对于第三范式的违反,但是我还是坚持:严格的一对一关系,就是应该写到各个表中,而不是独立作为一个表。

违反第三范式的好处在于:更少的Join。

而坏处在于:如果要修改,则要修改很多地方。例如Teacher和Student都有Contact,那么如果Contact要加一列Fax,那么要修改两处地方,这可能带来额外的错误。但是这个缺点因为使用了Model继承,将不再那么明显:修改Contact接口,然后修改实现了Contact接口的Teacher与Student的Model;因为有智能提示的存在,这样不会出错。

为了方便理解,我上传了源代码:点击这里下载

请用VS2010打开,VS2008我不确定能不能运行。请确保有本地数据库的权限。

打开之后直接运行,会在本地数据库生成DBaccess.B.Context名字的数据库。

在程序中我没有写数据迁徙,所以如果您修改了Model,要把之前生成的数据库删掉之后再运行;直接运行会报错。

如果想切换Model,将“Test”中的using Model.B改为using Model.A即可。

这也意味着切换数据库要修改命名空间。对于这个问题我还没有好的解决办法。本来是想用反射工厂来解决这个问题(代码中未实现的ModelFactory),但是反射出来的是Object,要As了之后才能用

如果有哪位大牛有解决办法,求告知,小弟在此跪谢。

现在实现了ModelFactory,使用了预编译指令来选择NameSpace:


  1. #defineA
  2. #ifB
  3. usingModel.B;
  4. usingDBaccess.B;
  5. #endif
  6. #ifA
  7. usingModel.A;
  8. usingDBaccess.A;
  9. #endif

若要切换Model,将#define B 改为 #define A 即可。