数据库与实体真的是一一对应吗?为啥学生-平均成绩这个例子与结论相反?
假如我数据库里设计的表是学生表:id,name,sex,score,class;
这样在数据库没问题,在项目中我新建一个实体Student:Name,Sex,Score,Class就可以。
但是在程序中如果要求每个班的平均成绩,分数标准差,方差这些外来的东西(在数据库和实体都没有,但是在中间过程求后,在最后要用到,所以不能用变量来存)
现在我想问的是下面哪种方法比较好,就是来保存(每个班的平均成绩,分数标准差,方差)
1.在我原来的实体Student上增加 平均成绩,分数标准差,方差这些 属性;
然后以每个班级的第一个同学(student first)为标记,计算后为这3个字段赋值,list<student> a=new list<student>,遍历所有班级,每次都添加班级的第一个同学a.add(first);这种方法是每个班的第一个同学的平均成绩,分数标准差,方差有正确的值,其他同学的这3个值都为0(这样感觉其他每个同学都存了3个无用的值,但是数据库“多对一"正适合这条规则啊)
2.再弄一个实体Class:平均成绩,分数标准差,方差,班级,专门来存在者3个值
请问到底用哪种方法好啊,谢谢!
------解决方案-------------------- 原则上说,实体和表一一对应是最容易理解的设计,但这样通常效率上会有所损失,一般都会为了效率而偏离这一原则,不过你的问题不是效率问题,
如果你用实体关系模型进行分析,你会发现有两个实体,扳机和学生,而平均成绩不是学生的属性,如果你一定要把平均成绩放在学生表中,会导致数据冗余,不仅占用空间,还对更新这些属性带来麻烦,
所以显然你的第一个设计是不好的,没理由使用,
------解决方案-------------------- 单就设计上来说,首先考虑的是界面层跟业务逻辑层的通讯,而数据层可以忽略。例如不同的人可能使用mongodb、sqlserver、db4o、oracle、excel、普通文件等等方式来管理数据,而他们全都看得懂从业务触发的实体设计。因此实体应该与数据库无关,而应该紧密结合业务逻辑和前端需求。
问题是很多人受到的“教练”就是那种套用模式的方式,自己想不出来设计。或者因为使用了某种DAL框架程序而受它的束缚。
------解决方案-------------------- 介绍一些实践:
(1)一些ORM允许你将实体绑定给存储过程或者视图。而存储过程和视图可以让一些字段来自动态的计算而不是数据库的存储,而在你的实体对象看来,它们和对应数据库的字段没有什么不同。
(2)使用C#的两个特性,一个是分部类,一个是扩展方法。
使用分部类的做法是,将这些额外的字段/方法写在分部类文件中,而和数据库对应的实体属性则由代码生成器去维护,这样兼顾了代码生成器的工作和你的程序。
或者使用扩展方法,将一个实体对象的操作放在扩展方法中,使得从api接口上看,它们似乎和实体类在一起,实际上编码却分开来。
(3)如果你自己设计ORM,你可以充分利用Attribute,来标记那些非数据库存储的字段,比如你可以设计这样的API
C# code
[TableName("table_students")]
class Student
{
[Field("ID")]
public int ID { get; set; }
[Field("Name")]
public string Name { get; set; }
[NavProperties("table=table_Scores", "key=StudentID")]
public List<Score> Scores { get; set; }
[SQL("SELECT AVG(Value) FROM Score WHERE StudentID = {0}", "{ID}")]
public int AvgScore { get; set; }
}
------解决方案-------------------- 1.从来没有任何一本书上说 数据表等同与逻辑实体,如果那本书是这么跟你说的,那本请烧了他,他对你没有任何用处 2.google:“BO,DO,DTO,model,viewmodel”这个东西??为啥有这么多不同的玩意。很简单,事实就是而已,每一层完成不同的任务,目标不同,自然所需要的对象不同。 我们不从一而终,如果逻辑上需要我们组合,需要我聚和,干嘛不呢?为啥要围绕一个让你别扭的固定“实体”打转呢?
------解决方案-------------------- 再写一个类 继承user类 再加上你所需要的字段属性
------解决方案-------------------- 探讨 再写一个类 继承user类 再加上你所需要的字段属性