chiname

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

我的一种实体对象的设计方法

我的一种实体对象的设计方法

   

基类DatabaseEntity有三个方法Insert/Update/Delete,分别执行插入/更新/删除操作,Insert方法的参数values为一个键/值对的集合,表示如果传入了此集合的键/值对就会被作为插入的数据,

              实现过程为:  

        public void Insert(NameValueCollection values)

         {
              System.Text.StringBuilder sqlbuilder = new System.Text.StringBuilder("INSERT INTO Prodcut");

              sqlbuilder.Append("(");

              for(int i=0; i<values.Count; i++)

              {

                   sqlbuilder.Append(values.Keys[i]);

                   if (i != values.Count - 1)

                   {

                       sqlbuilder.Append(",");

                   }

              }

              sqlbuilder.Append(") VALUES(");

              for(int i=0; i<values.Count; i++)

              {

                   sqlbuilder.Append(values[i]);

                   if (i != values.Count - 1)

                   {

                       sqlbuilder.Append(",");

                   }

              }

              sqlbuilder.Append(")");         

// then execute sql statement

         }

Update/Delete与Insert一样的道理,都是根据传入的NameValueCollection构造出合适的SQL来执行,其中Update方法的第二个参数primarykeys为更新所需要的条件的键/值对,更新的时候更新满足primarykeys集合中key=value的条件的数据就可以了(这种条件的限制就很简单了,可能一些地方满足不了要求).

 

    在派生类Product和MerchantProduct中,分别提供的自己的Insert/Update/Delete方法的实现。此方案与别的不一样的地方就是在每个实体类中,为每个属性单独设置一个修改标志,比如:

    public class Product : DatabaseEntity

     {

         private int _ProductID;

         public int ProductID

         {

              get { return _ProductID;}

              set

              {

                   _ProductID = value;

              }

         }

 

         private bool _ProductNameModifyFlag;

         private string _ProductName;

         public string ProductName

         {

              get { return _ProductName;}

              set

              {

                   if (_ProductName != value)

                   {

                       _ProductNameModifyFlag = true;

                       _ProductName = value;

                   }

              }

         }

 

         private bool _PriceModifyFlag;

         private float _Price;

         public float Price

         {

              get { return _Price;}

              set

              {

                   if (_Price != value)

                   {

                       _PriceModifyFlag = true;

                       _Price = value;

                   }

              }

         }

     }

然后在Product的Update方法中就可以如下实现:

        public void Update()

         {

              NameValueCollection values = new NameValueCollection();

              if (_PriceModifyFlag)

              {

                   values.Add("Price", Price);

              }

              if (_ProductNameModifyFlag)

              {

                   values.Add("ProductName", ProductName);

              }

              // ……

              NameValueCollection keys = new NameValueCollection();

              keys.Add("ProductID", ProductID);

              base.Update(values, keys);

         }

就是分别判断每个属性的修改标志是否为true,如果为true那么就需要更新此属性对应的数据字段,否则不需要更新。其Insert方法不需要此判断,可以把全部的属性值都插入,而Delete方法则可以根据自己的需要执行删除(比如有些数据在数据库中是假删除的,那么就可以调用Update方法来实现)。

     此方案没有涉及到专门查询的操作!查询用另外一个专门的搜索系统来实现。我在上面的代码很多细节方面值得商榷,UML图也有点不对的地方,不过细节不是重点,重点讨论这种方案模式。另外DatabaseEntity完成的功能在这里实际上是一些数据存取操作,Product和MerchantProduct也可以不从他继承,具体可以怎么合理怎么来用。

    点评:此种方式的核心是Update方法,DatabaseEntity的Update和Product的Update,而Insert和Delete则比较简单。这种方式不是O/R Mapping,而是一种封装的方式。

优点1、由于加入了修改标志的判断,不需要根据业务再写很多Update方法了,功能集中。

          2、隐藏了操作的细节,给使用者一种完全面向对象的体验。

          3、代码复用性高了,针对实体不需要写那么多数据库操作方法。

4、此方式在一定范围内还是比较有效,并且实际操作的代码都是自己写,性能好坏可以自己控制。

    缺点:1、如果很简单就可以搞定更新的操作,那么写就先得比较繁琐,要写很多代码。

            并且如果更新的需求很复杂,这种方式也不能很好的满足要求,主要是更新条件不好控制(上面已提到)。

          2、不好实现事务,比如图中的ProductInfo的Insert/Update/Delete就涉及Product和MerchantProduct两个类(对应两张表),不过可以考虑使用System.EnterpriseServices.ServicedComponent(慎用)。.Net2.0中有TransactionScope,可以解决这个问题。

            3、需要专门设计细粒度的对象用来避免多张表的操作,因为DatabaseEntity并没有针对多表操作来设计,当然也可以另外设计DatabaseEntity来支持此特性。

Email: qingping.hu@gmail.com

posted on 2005-11-28 10:26 yzx110 阅读(631) 评论(11)  编辑 收藏 收藏至365Key 所属分类: 技术随笔

评论

# re: 我的一种实体对象的设计方法   

假如能扩展到ADO.NET参数形式处理及得到存储过程的支持就更好了
2005-11-28 11:06 | 垃圾猪

# re: 我的一种实体对象的设计方法   

就从Insert这个方法的命名上,就不能给人以面向对象的感觉。
在面向对象世界中应该使用Add这样的命名方式。
2005-11-28 11:07 | 风满袖

# re: 我的一种实体对象的设计方法   

re 删除评论:
说的有道理,这个我就没考虑到了,多谢指正。
我没用O/R Mappng,也是初次尝试这种方式。
2005-11-28 13:10 | yzx110

# re: 我的一种实体对象的设计方法   

我以前也这样写过,新增与删除与楼主的写法相同
不过我更新时,我是直接送一个参数名值对的集合进来,动态组成SQL语句来做的
简单查询的写法也同理。

然后上面一堆方法全是自动代码生成的,数据访问层除了写一些复杂查询的方法外,需要写的代码很少
2005-11-28 14:41 | lichdr

# re: 我的一种实体对象的设计方法   

晕 能不能写下 NameValueCollection 类
2005-11-28 14:58 | mkimtaehee

# re: 我的一种实体对象的设计方法   

我晕...数据类型有各种各样,就你的方法,如果是字符串类型就成了
insert into atable (name) values (我的商品)
就更不要提blob类型了
这样的语句能运行吗?

如果数据访问封装这么简单,MS的人应该失业了。你看他们把个ADO.NET搞得几复杂。
2005-11-28 23:57 | 双鱼座

# re: 我的一种实体对象的设计方法   

针对数据操作这部分,个人认为,至少要封装到ParameterCollection为参数传递的步骤吧,否则那不是要每个一个实体就都要写一遍?

我简单的写了段code,你看一下
点击查看

其实最简单的就是以强类型的dataset中的table为实体,只需要封装一下与db操作的那块就好了.

这样就比较接近表模式了.而且实现起来够简单.

2005-11-29 00:36 | Young

# re: 我的一种实体对象的设计方法   

insert tables (field1,field2....) values(@field1,@field2,.....)
这样就没有数据类型的问题。当然这些参数都是严格命名的。反正都是自动代码生成,也不费什么力气。

所以传进来的参数集合也是不能乱传的。
在UI层从绑定的控件中可以读得它所绑定的Field名。提交数据的时遍历一下FORM上的控件,可以自动组成一个符合要求的参数集合出来。

这种用法碰上复杂应用,FORM比较复杂,有复杂的商业逻辑的时候,当然有很多问题。但简单的增删改,查询还是可以胜任。

PS:.net写个简单数据操作的程序也比较复杂(不用DataGrid),比起DELPHI来
2005-11-29 10:39 | lichdr

# re: 我的一种实体对象的设计方法   

本身设计一个东西就不要求全。够用就行了。
2005-11-29 10:47 | lichdr

# re: 我的一种实体对象的设计方法   

我更晕...
>>反正都是自动代码生成,也不费什么力气
哪里说的自动代码生成?

>>够用就行了
这话等于没说,反正傻瓜都知道。傻瓜不知道的是:什么叫够用。

>>但简单的增删改,查询还是可以胜任
简单的增删改和查询还用得着做任何封装吗?难道DataSet不够用吗?难道以上设计包括加上你做的参数集合的封装一起,比DataSet有丝毫的强吗?
2005-11-29 11:32 | 双鱼座

# re: 我的一种实体对象的设计方法   

@搂主:

你这只能算最最简单的对数据库操作的封装,简单到有无数的漏洞,连最简单的SQL注入都防范不了,更不要说作为一个实际可行的方案了。

“本身设计一个东西就不要求全”--这样的心态是做不出好作品的。正确的话我想应该是:“没有最好的方案,对特定的项目,选择最适合的方案就好”。

你的这个设计,脱离你的项目来讲,我可以说一句,基本没什么通用性,重用的价值几乎小到0。当然了,不排除对于你的某个项目来讲完全够用的可能。

不过,既然是写文章发到首页来,还请谦虚一些。如果只想接受拍转,不愿承受鸡蛋,那还是不要public为好
posted on 2005-11-29 19:12  把我的欢乐带给你  阅读(116)  评论(0)    收藏  举报