关于Model数据实体层,欢迎大家来讨论。
请问大家是如何处理以下问题:
Model是数据库表的实体映射,当系统的需求出现新的变换,例如增加新的功能时数据库需要增加新的字段,
或需要去掉和更换某些旧的功能,那么对应的数据库字段肯定是会修改的。如果数据库的表结构有变换,
对应实体Model层肯定有变换。
改一个字段,
Model层必须要修改,
那么DAL层必须要修改,
SQL语句必须要修改,
表示层的数据展现也是依赖Model层的属性名称,也要修改。
这不符合设计模式的单一职责。牵一发动全身。
并且这样设计,那用啥设计模式都是白搭。
其次工作量非常大,例如商品表的话 光执行查询的地方就不得了。
请问大家是如何处理这种问题,或者怎么把影响降到最低。
[最优解释]
我也有这样的困惑,关注
[其他解释]
其实只需要model变就可以了,其他都可以不用变的,
如增加model的语句,可以根据model的属性来动态生成一个sql语句
public string GetInsertQuery(string prikey, string tableName)
{
List<string> fields = new List<string>();
foreach (PropertyInfo pi in this.GetType().GetProperties())
{
fields.Add(pi.Name);
}
StringBuilder query = new StringBuilder("insert into " + tableName + "(");
StringBuilder value = new StringBuilder(" values(");
int index = 0;
int count = fields.Count;
foreach (string key in fields)
{
query.Append(key);
value.Append(prikey + key);
if (index < count - 1)
{
query.Append(",");
value.Append(",");
}
++index;
}
query.Append(")");
value.Append(")");
return query.ToString() + value.ToString();
}
[其他解释]
可使用LINQ
http://topic.csdn.net/u/20090926/11/af162995-f4f8-4660-bed7-3949f047bde3.htmlhttp://topic.csdn.net/u/20100207/09/237128f5-a14a-44e6-a2b3-6920bc6e9538.html
[其他解释]
楼上的方法貌似 根据实体的属性名称来生成各种需要执行的SQL语句?
这也只能减少改动DAO的SQL语句 如果增加了字段。
SqlParameter还是会改变 或者是用存储过程的呢。
有没有符合设计模式原则的解决方法呢?
[其他解释]
更正一下,其实要表达的意思就是 能否对Model层进行抽象 封装变化点。
但Model层可能会随每次需求变更而更改。目的就是想只需变更Model的情况下,不影响引用它的地方。
[其他解释]
没人回答吗?自己顶起来
[其他解释]
请楼主一定坚持下去,楼主提到的问题很好,一个本该在学校就解决的问题,却没有人回答,
楼主如果是负责设计架构的,你可以换一种思维模式,你先把整个架构画出个草图,看着架构问问自己:
1、你的整个构架里为什么会有Model?
设计Model的动机?难道就是因为书上说要搞Model?
如果设计这个名叫"Model"的东西是为了所谓的映射数据库、类型化数据集,我认为是与OOD背道而驰的,
数据本来就是弱类型的、不稳定的,却偏有那么一号人要把这些在项目中描述并且还要“持久化”
2、现有架构里的Model干了什么,达到设计要求了吗?
从设计角度看:到底是先有的Model还是先有的数据库?
老师是怎么教UML的?模型驱动,整个开发所有事务都是由模型驱动的,哪个人说是数据库驱动的!
[其他解释]
接7楼:
3、我认为Model不是“实体”,是“模型”,也就是Model的职责是描述整个项目,定义everything,根据OOD的设计原则,Model应该设计成数据无关的,Model的实例可以存放在任何一种形式的DB里,比如XML、Sqlserver、Access、Excel等等,
4、如果需要修改或添加一个字段,那么要做的实际上是对Model的一个实例或者说副本进行修改(请记住刚才说了:不在代码里,在db里),根本不需要修改model的代码,更谈不上修改BLL和UI了;
5、任何一种类似于petshop的架构和类似于codesmith的代码生成器都不是终极生产模式,这些东西只能作为一种过渡的手段使用,那和复制粘贴代码没什么区别,当然我不是说复制粘贴代码不好,恰恰相反,在迈向技术成熟的历程中,我认为复制粘贴越多越好,但是复制粘贴并不是终极目标,只是重构的第一步:让更多的代码无差别;
6、在一个成熟的生产线上,其实是不需要Coder的,极少量的Code由Designer代理了,请注意:不是Coder代理Designer。
[其他解释]
model是整个架构的核心
我就是一菜鸟,个人观点仅供参考,抛砖引玉,那位大侠如果有不同意见请明示
[其他解释]
说了这么多,还没一个人说出实际解决办法,如何降低Model修改对其他层的影响呢?等待CSDN高手解答,自己顶起。
[其他解释]
7楼说的很好。我会坚持下去。
这个问题的确是在学校就该解决了,老师只告诉我们要这样做,这样做是对的,但是为什么呢?有的只说一些大道理 空话来忽悠我们。我们要的是实际
但据我发现 不管是老师讲课或者网上的设计模式都没有讲到过这个问题,
或是在回避这个问题。
看到的所有关于设计模式的文章 博客 书。都是针对某个功能,某个需求来设计。
都没有把数据和属性的加到例子中来。
[其他解释]
其实这种问题很深的,不是一两句话就可以讲清楚的,慢慢积累!
[其他解释]
遇到这种问题,我会跟你说:把数据库表结构恢复原样去!
只有实体Model的设计有变化,才需要改变数据库表结构。本末倒置自然找出很多麻烦。
[其他解释]
实际上我们在ORM领域说过很多次,有不少人脑子里首先是数据库表、SQL语句等等,所以就不可能自动化了。实际上,这些貌似体现你的“本事”的东西,都应该自动化,而不需要你手工编写。因此,ORM的目的就是在开发时多种辅助重构工具来辅助程序员从O自动映射到R,最终开发大多数软件时不需要任何DBA人员(只有后期维护时需要一两名),而反过来以为是关系数据库来映射出对象模型则是本末倒置。
[其他解释]
介于吴伟同志在本版的影响力,希望吴伟同志能否开一贴专门批判一下“数据库驱动思维”
[其他解释]
把数据库表结构恢复原样去?
请问能否解决 新的需求变更造成 数据库改动 并且 把影响程度降到最低.
可能是您的话太高深,小弟理解能力有限。还请详细说明,感激不尽。
[其他解释]
需求变更 总要把数据存入数据库呀,
改模型不一样会对引用它的层造成影响吗?
[其他解释]
还要说多少遍呢?
需求变更后修改的是模型,不是数据库!
[其他解释]
您讲的非常好。
能否讲下您使用ADO.NET是如何设计 可根据新的需求来扩展并很少影响其他地方的架构呢?最好能有代码或者图形的例子哈,非常感谢您。
[其他解释]
那么什么是“改模型”呢?
看看你做过的模型,你的模型可以是一个interface吗?如果只能是class显然是非常不够的。即使是class,你的class定义会扩展吗?例如增加了5个属性、8个方法?
这些变化,在表现层和DAL都不需要重写。最多遇到的有缺陷的“三层”是每当Model变化时就修改DAL,而如果此时你还要修改表现层就完全是繁冗的了。与其如此,还不如不用什么三层做法。
[其他解释]
up收藏up收藏up收藏up收藏up收藏up收藏
[其他解释]
楼主问题的根源在于:“Model是数据库表的实体映射”,所以由此进行的所有推导都是错的。
一个很流行的说法,是先有实体,再有数据库!(虽然做起来实际上很难,呵呵)
所以楼主应该理解成:数据库是model的存贮工具。然后,当model发生变化时,再考虑数据库是否要进行更改……
由于在model中可以进行各种抽象,其实model中的类和数据库中的表并不一定要一一对应的,如果一定是一一对应,dataset就够了,要实体类干嘛?
[其他解释]
MARK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[其他解释]
自己写一个根据数据库改变而全部改变的工具,比如改变model,dal,bill层,我就是这么做的。做好数据库就可以了。修改数据库再点一次工具句可以了。
[其他解释]
"改一个字段, Model层必须要修改,那么DAL层必须要修改,SQL语句必须要修改,表示层的数据展现也是依赖Model层的属性名称,也要修改。 这不符合设计模式的单一职责。牵一发动全身。 并且这样设计,那用啥设计模式都是白搭。 "
我觉得楼主对多层架构理解有误区,多层架构不等于设计模式,同样多层架构也不是用来解决某些变化的.
如你所说的场景中首先是数据结构发生了变化,那么可以说在DAL层使用"自动生成SQL的ORM"是不合适的,因为DAL是依赖Model的,正如你说的"牵一发动全身".所以说对应你的需求,你的程序设计是失败的(在应对变化方面).如果要寻求一种相对好点的解决方案的话,我觉得类似于ibatis的处理方式似乎适合你的需求,它将Model映射和数据处理逻辑分离到配置文件中,这种方式将代码级变化降低了很多,同时方便了变化后的修改,楼主不防详细了解下它的功能.
P.S. 设计模式是人创造的,它不是小叮当,不要认为它会给你一切.
希望对楼主有用.
[其他解释]
源于此贴中各位的回复,看来本人需要重新去研究下三层框架的东东了,学习贴,顶。
[其他解释]
楼主的问题很尖锐,作为一个新人,我倒是觉得没必要考虑这么多,当需求变更时,原来的model不适用了,那就换一个,虽然代码翻新量较大,但是也无可厚非,非要一劳永逸,弄个小项目还去考虑其需求变更的问题,我觉得是累赘了,一个项目真要能做成楼主那样,我觉得咱这些做程序员的都可以回家洗洗睡了,以前人们常说:coder是个体力活,我看连体力活都省了,直接做个楼主描述的项目,以后有业务需求变更的稍加改动,生成一下就OK,谁还愿意花钱雇佣coder... ...
[其他解释]
我自己做了个自动编码的影射工具,可以解决这个问题.
[其他解释]
up
[其他解释]
哎,你们为什么不出一本书呢~
[其他解释]
今天在公司加班,偶然看到这个帖,心血来潮,我也发表下我的见解:
无论前期需求调研多么详细,最终该变的还是会变,为什么要用三层开发?其实是将原本结构化的数据库装饰成面向对象。
数据库表结构变化了,那么毫无疑问,程序员从表结构改起,实体,数据访问层,直到改界面代码,项目经理也跟着改文档,这一过程相当之烦,我针对这样的问题说说我的解决办法:
方案一:为自己的项目写代码生成器,至少可以根据表生成实体和数据访问层,这样在表结构发生改变的时候你重新生成出MODEL和DAL,覆盖老版本,OK,这样做实际上和手工改没有什么区别,不过是由程序去完成。
方案二:利用反射,也就是所谓的ORM,根据已保存的表结构配置文件或实体对象,通过反射生成出各种不同业务的SQL语句,以至于你提供一个实体,就能新增,删除,修改等等操作。请看下面一个实体,你也许会明白:
[tableInfo(tableName="sys_user",primarykey="id",foregintbl="base_employee")]
public class sys_userInfo
{
[columnInfo(columnName="ID",allownull="false",defaultname="编号")]
public int id{get;set;}
[columnInfo(columnName="LoginName",allownull="false",defaultname="登入名"]
public string loginName{get;set;}
[columnInfo(columnName="passwordd",allownull="false",defaultname="密码"]
public string password{get;set;}
//……
}
上面这个实体肯定和你日常开发的实体有所不同,你想想通过反射,是否能生成出对应的新增修改删除等其他SQL语句,甚至生成出界面,所以当需求改变,你再利用代码生成器生成出这样一个实体,就完事。
[其他解释]
看了大家的评论后,我突然有种醍醐灌顶的感觉。不仅仅是从技术层面,还有社会层面。首先就是“数据库驱动”还是“实体类驱动”就值得商讨。是否是model就一定成为驱动所有的核心。这样做是否更加便捷,如果把model层又分出接口,是否成为另外一种负担,虽然扩展性更好。我觉得改变model后,需要改dal并没有什么可怕的。
不要把一个问题复杂化,从编程思想来说,讨论这个问题有价值,从实际上来说,这个没有价值的,首先你要确定你项目的存活周期,以及你项目的大小,如果只是一个中小项目,或者存活不到两年,并发人数不过百人。那么是否有需要大炮打蚊子。
按照楼上几位的说法,其实有点偏题,别人问的是如果能完成改变数据库或者实体类,能够不影响和改变其他层。而不是问究竟是实体驱动,还是数据驱动的问题。需求变更了,你的实体类不可能做到一开始就面面具到,虽然实体类不需要跟数据库一一对应,但是你免不了需要修改实体类的时候,如果修改了实体类,绝对要涉及到DAL以及BLL。比如需求要增加一个“性取向”(不要说我粗俗,只是为了说明有时候不是什么都能考虑到),你必然要修改数据库,实体类,数据层,甚至界面。
我觉得楼主问的问题,不能称为一个真正的问题。你问的问题是操作层面的事,下面很多回答的都是建模思想层面的问题。这种问题不用考虑,无中生有一个东西,必然每个地方都要改点。只是设计的尽量避免修改跟这个字段不相关的类,不然只是一个垂直修改而已,不要造成横向修改就行了,这本身就保障了一定的扩展性,试问如果不用多层结构或者模式的思想,每个页面就是一个数据层+业务层+实体层,你可能需要修改一大片横向相关的代码。而且非常混乱。
[其他解释]
学习!!!!!!!!
[其他解释]
说白了,还是没有理解体会到面向对象编程思想的精髓… 请高手指教。
[其他解释]
该回复于2010-04-14 13:49:01被版主删除
[其他解释]
该回复于2010-04-14 13:53:16被版主删除
[其他解释]
学习,UP~~~
[其他解释]
mark
[其他解释]
利用attribute特性,动态解析实体与关系表之间的映射(即动态解析OR),这样的话就只需要修改modle即可了。
[其他解释]
向前辈们学习
[其他解释]
我也知道,要做到这个样子,不是一两天的事情,但是,有哪个高手能给出来这样的一个例子不,很想了解下要达到上面这个效果的Model是怎么设计的,非常感谢
[其他解释]
友情帮顶下!顺便学习学习!
[其他解释]
但是当你遇到多表查询的时候 比如 一个比较复杂的SQL语句的时候……
[其他解释]
根据你的项目大小决定是否分层,如果是小项目那分层只会令项目更繁锁。但大项目分层的特点就会很明显了,把各模块能合理的划分出来,最简单就是三层了,就是所谓的表现层->业务逻辑层->数据库访问层(数据库持久层)。通过合理的接口就可以实现多人协同开发,大大增快项目的进度。。
[其他解释]
不要人家说3层好咱就3层
软件规模小 只为了处理某个简单问题 就不要想MVC ORM Framework 自己找罪受
因为调用点少 与其多层 还不如一个一个改呢...
但是如果系统的业务逻辑很复杂 还是强迫自己使用这些东西吧 这些都是前辈的血泪教训
model你就不能让它跟数据库联系到一起 model有什么属性?有啥功能?是你系统设计时就定好的。
而数据库 只是你存储你的model的地方
[其他解释]
我对分层的理解:
1、分层提高程序的移植性,可以在c/s和b/s之间转换,换下表现形式即可
2、分层提高程序的灵活性,当应用逻辑发生变化的时候,重写逻辑即可
3、分层使得开发分工明确,数据库定好了,做数据开发的做数据开发,做逻辑的做逻辑,做UI的UI互不干扰。只是个时间顺序问题。
...
好多,大家可以补充补充
[其他解释]
个人认为,上面提到的特性方法解决该问题,界面是不是最终还是得程序员改呢?我曾经的一个项目中为了解决这个问题,花了很多时间在程序中提供了表单设计器的功能,考虑到复杂度,并没实现关联的查询之类,仅仅解决了单独的实体增减字段的需求,总结是,花了大量的时间仅仅提供了一个不常用的功能,回头想想,对与其增减字段还不如在每个地方手动的改代码呢!
[其他解释]
可以做个取舍……
[其他解释]
没有讨论出结果来啊
[其他解释]
如果你数据表发生变化,那么数据随之改变是不可改变的现实,但又不可说设计模式再也没作用。
因为你使用了适当的分层开发,那么受影响的应该只有是数据层,你只需要改变一下Model和DAL,而对应该的DLL应该受影响很少,这正正是分层带来的好处。
如果你没有正确使用正确设计模式,可能影响会更大。
我也遇到到相同的问题,客户的要求常常改变,所以有时候会数据库有影响,后来我用了另一种方式解决,就是通过一个从属关系建立一个附属表格,里面记录需要新建的列,从而使对DAL影响降到最低。
当然这不可能完全解决问题,但也不失为一个可行的方法。
[其他解释]
用Linq to SQL,数据表改了,删掉,再拖一个过来,就OK了,不费脑子不费事
数据的保存,更改,全对象化,Easy
多表联合查询,匿名类,随意定制,要多方便有多方便。
有人说Linq to SQL 已死,有人说Linq to SQL会有性能问题,不要相信他们说的,你自己试下,生成的SQL语句比很多人写的效率还要高。
如果非要说性能,就是解析表达示树时的性能。一般项目根本不成问题。
[其他解释]
学习学习.... 我觉得不管三层还是其他的 .只要能让程序性能变好,方便,不繁琐..该用什么就用什么
[其他解释]
抛弃Data centric first, 改换Domain-Driven first,就可以极大的消除你的问题。首先,建议停止使用ADO.NET,而选用合适的ORM Tools,比方说 NHibernate 或者Entity Framework。这样一来,你面对的是Domain Entities/Objects,也就是说,先有Domain Model, 后产生数据库。你甚至可以不必太关心Database, 也不用写任何Stored Procudure, 因为NHibernate 或者Entity Framework 会为你做任何事情。比方说,数据库可以自动生成,LINQ可以取代Stored Procudure等。当需求发生变化时,你首先要修改的是Domain Model,而不是Database。#14楼说的很明白了,现代软件设计与开发,DBA远不如以前重要了。
[其他解释]
+1
[其他解释]
曾经做过linux下的嵌入式开发。用C语言,一个结构体传来传去的。现在用着所谓的三层,一个叫传输对象的类传来传去。难道,这就是所谓的OO。与以前的开发,并没有看到不同嘛。我在迷茫中。
我想,我们平时是这样写的
A.Insert(new B());
或许我们可以考虑下另一种思维,
A.讲话(一定的格式。可以是一个结构类,或者是字符串);
介质来传播,传到合适的地方。
通过类似于松耦合的事件,广播,责任链,有一个对象,听到了呼唤,回应。
B.执行(.....);
讲的不清楚。当是看神话故事了。
[其他解释]
楼主显然是按照 Data Centric first methodology,所以你提的问题是采用这种方式普遍遇到的。我觉得应该改变思路,使用Domain Driven first,就会使应用程序设计变得有趣和轻松。建议读以下的书:
Domain-Driven Design: Tackling Complexity in the Heart of Software
Applying Domain-Driven Design and Patterns: With Examples in C# and .NET
[其他解释]
学习了
------其他解决方案--------------------
其实自己有代码生成器,效果还是可以的。覆盖秒杀哦。
[其他解释]
学习了 数据库驱动开发真的是很累人的
[其他解释]
呀,这个贴子太精辟啦,学习学习再学习~~~~~