支持差异数据保存的数据库实体类设计(二)(续)

首先声明一下,小虾的写文章的水平那是相当的两字——很菜!所以碰到看不明白的文字,请大家留言,我会作特别回答。

 

下面直接入正题。

 

自定义数据库实体类测试版已经出炉(编程语言为C#),支持差异数据保存,0反射,几乎是0查询语句,效率在一定程度上也是很客观的,但是还没有跟原始的DataTable数据绑定进行对比,这个工作留着下一步完成,先说本文重点。
1、支持差异数据保存

如果想做到这一点, 大家最容易想到的就是添加一个标记,用于记录当前属性的值是否被修改过。

先上一段传统的数据库实体类的设计方法:

public   class  Entity
{
    
public   int  IntValue{ get set  ;}
    
public   int  StringValue{ get set  ;}
    
public   int  BoolValue{ get set  ;}
    
public   int  DoubleValue{ get set  ;}
    
public   int  DateTimeValue{ get set  ;}
}

 

 

 

如果简单的通过在实体类中添加一个标记来记录每个属性是否被修改过,当然是不可行的,因为你根本就不知道每个实体有多少个属性,而且你还必须在每个标记和属性之间建立联系.这个时候,一个数据类型对象浮现在脑海中,就是放弃传统的int, bool, string, double, DateTime这些数据类型,当然也不是完全放弃,只是对这些简单类型进行一次封装,这样字一个初步的数据类型对象就产生了:

ExpandedBlockStart.gif View Code
1  public   class  MInt
2  {
3       public   int  Value{ get set ; }
4       public   bool  ValueChanged{ get set ; }
5  }

 这样传统的数据库实体类就要做适当的调整了:

ExpandedBlockStart.gif View Code
1  public   class  NewEntity
2  {
3       public  MInt IntValue{ get ; set ;}
4       public  MString StringValue{ get ; set ;}
5       public  MBool BoolValue{ get ; set ;}
6       public  MDouble DoubleValue{ get ; set ;}
7       public  MDateTime DateTimeValue{ get ; set ;}
8  }

 为了能够更好的支持DBNull类型的数据保存到数据库,需要在数据类型对象添加一个标记IsNull,这样在进行数据保存只要判断对象是否为空,如果为空,则在更新,或者插入数据的时候,直接赋值DBNull.Value即可,这里只是对数据类型对象其中的一小块扩展,下面还会有很多其他的,请继续往下走。

  2、0查询语句

说到0查询语句,小虾在这里说了句大话了,不管怎样,先看看小虾是如何实现的吧。

小虾的查询语句包括4种类型:Select, Delete, Update, Insert;做过开发的人都知道,每次新增加一个实体对象,都需要写一大堆的查询语句,简直是揪心。不过等你看了这篇文章以后,相信你从此就不用再揪心了。

 文章开头提到了0反射,但是不通过反射又如何获取实体对象中的每一个属性的名称呢?大家很容易想到的就是枚举了,对,我也是这么想的,通过集合的方式,将实体对象中的所有属性都装到集合中,小虾准备用IList<T>。但是新的问题又出现了我们的实体对象的属性的类型是MInt, MBool, MString。。。如何让他能够支持IList<T>呢。所有需要对原始的数据类型对象进行一下修改了,让他们全部继承自一个对象TypeBase不就行了吗?这样一个数据类型对象基类就产生了:

ExpandedBlockStart.gif View Code
 1  public   abstract   class  TypeBase
 2  {
 3       ///   <summary>
 4       ///  值
 5       ///   </summary>
 6       public   abstract   object  ObjectValue {  get set ; }
 7 
 8       ///   <summary>
 9       ///  是否为空
10       ///   </summary>
11       public   abstract   bool  IsNull {  get set ; }
12 
13       ///   <summary>
14       ///  值是否改变
15       ///   </summary>
16       public   abstract   bool  ValueChanged {  get set ; }
17  }

 按照上文将的,为了能够达到遍历实体对象内部的每一个属性,而且达到0查询语句的效果,我们的自定义数据库实体类就应该再一次进行修改了:

ExpandedBlockStart.gif View Code
public   class  NewEntity
{
    
#region  静态对象, 数据库表名,字段名
    
// 表名
     public   static   string  TABLENAME  =   " NEWENTITY " ;

    
// 数据库字段名
     public   static   string  INTVALUE =   " IntValue " ;
    
public   static   string  STRINGVALUE =   " StringValue " ;
    
public   static   string  BOOLVALUE =   " BoolValue " ;
    
public   static   string  DOUBLEVALUE =   " DoubleValue " ;
    
public   static   string  DATETIMEVALUE =   " DateTimeValue " ;
    
    
#endregion

    
#region  属性成员

    
// 属性结合,用于存放该实体对象的所有属性,以便于之后的遍历
     public   IList < TypeBase >  ListField{ get private   set ;}
    
    
// 数据表名,一边能够通过实例成员获取到该实体对象所对应的数据库表名
     public   string  TableName { get return  TABLENAME; }}

    
// 实体属性
     public  MInt IntValue{ get ; set ;}
    
public  MString StringVa;}
    
public  MBool BoolValue{ get ; set ;}
    
public  MDouble DoubleValue{ get ; set ;}
    
public  MDateTime DateTime;}

    
#endregion

    
#region  构造函数    

    
// 无参数构造
    
// 在构造对象的时候,小虾将每个字段的数据库字段的字段名引用传输属性中保存,也是为了方便只有在遍历
    
// 属性集合的时候,能够获取该属性的值,同时能够获取到该属性对于的数据库字段名
    
// 用ref传参,是尽量保证一个数据库字段名,在内存中只有一个引用,在一定程度上减少了内存开销
     public  NewEntity()
    {
        
this .IntValue  =   new  IntValue( ref  INTVALUE);
        
this .StringValue =   new  StringValue( ref  STRINGVALUE);
        
this .BoolValue =   new  IntValue( ref  BOOLVALUE);
        
this .DoubleValue =   new  DoubleValue( ref  DOUBLEVALUE);
        
this .DateTimeValue =   new  DateTimeValue( ref  DATETIMEVALUE);

        
/// 将所有属性添加到属性集合中
         this ._AddFieldToList();
    }
    
    
// DataRow对象构造
     public  NewEntity(DataRow row)
    {
        
this .IntValue  =  Convert.ToMyInt(row[INTVALUE],  ref  INTVALUE);
        
this .StringValue =  Convert.ToMyString(row[STRINGVALUE],  ref  STRINGVALUE);
        
this .BoolValue =  Convert.ToMyBool(row[BOOLVALUE],  ref  BOOLVALUE);
        
this .DoubleValue =  Convert.ToMyDouble(row[DOUBLEVALUE],  ref  DOUBLEVALUE);
        
this .DateTimeValue =  Convert.ToMyDateTime(row[DATETIMEVALUE],  ref  DATETIMEVALUE);
        
        
/// 将所有属性添加到属性集合中
         this ._AddFieldToList();
    }

    
#endregion

    
#region  私有方法

    
/// 将所有属性添加到属性集合中
     private   void  _AddFieldToList()
    {
         
if ( this .ListField  ==   null this .ListField  =   new  List < TypeBase > ();
         
this .ListField.Add( this .IntValue);
         
this .ListField.Add( this .StringValue);
         
this .ListField.Add( this .BoolValue);
         
this .ListField.Add( this .DoubleValue);
         
this .ListField.Add( this .DateTimeValue);
    }
    
#endregion   
}

展开代码,一看这么多行,可别直接一拖到底,仔细的研究一下,有了这样一个实体类才能够满足我们的0查询语句。

有一点要提出来的就是,我在每个实体属性对象中加了两个字段:ColumnName,该字段通过构造函数中给每个属性赋值的时候传入, 在这里还是贴一下代码,方便下文调用,同时也给大家少一些疑惑:

ExpandedBlockStart.gif View Code
public   abstract   class  TypeBase
{
     
///   <summary>
     
///  值
     
///   </summary>
      public   abstract   object  ObjectValue {  get set ; }
 
     
///   <summary>
     
///  是否为空
     
///   </summary>
      public   abstract   bool  IsNull {  get set ; }
 
     
///   <summary>
     
///  值是否改变
     
///   </summary>
      public   abstract   bool  ValueChanged {  get set ; }
 
     
///   <summary>
     
///  该属性对应数据库字段的字段名
     
///   </summary>
      public   abstract   string  ColumnName{  get set ; }
}

 至于里面其他代码的用意,在这里就不多讲了,看注释基本上就能够懂了,还有问题的,请留言,我会做特别回复。

 3、如何实现0查询语句

能看到这里的人,说明你真正关注的是,如何做到0查询语句,下面小虾就来讲讲如何实现0查询语句。

在将如何实现0查询语句之前,我这里有一个特别的说明,就是在每个数据库实体对象中,你必须保证有一个主键字段:MyInt ID,这样我们在update和delete的时候就可以通过这个唯一字段来处理。

直接上代码:

ExpandedBlockStart.gif View Code
// 保存对象
public   bool  Save()
{
    
if ( this .Id.Value  =   0 this .Insert();
    
else   this .Update();
}

// 插入对象
public   bool  Insert()
{
    
// 这里通过一个公共方法,获取该对象的下一个Id
     int  Id  =  Utils.GetNextId( this .TableName);
    
string  sql1  =   " INSERT INTO  "   +  tb.TableName  +   " (Id " ;
    
string  sql2  =   " ( "   +  Id.ToString()  +   " , " ;
    
foreach (TypeBase tb  in   this .ListField)
    {
        sql1 
+=   " , "   +  tb.ColumnName;
        
// 这里说明一下tb.ToString()方法需要在每一个种类型中进行重写
        
// 如MyInt类型的对象的ToString()的返回值直接是ObjectValue.ToString();
        
// 如MyString类型的对象的ToString()的返回值直接是"'" + ObjectValue.ToString() + "'";
        
// 等等,其他的就不多说了。
        sql2  +=   " , "   + tb.ToString();
    }
    sql1 
+= " ) VALUES "   +  sql2  +   " ) " ;
    
// 然后再执行数据库命令
     return  DbHelper.ExecCommand(sql);
}

// 更新对象
public   bool  Update()
{
    
// 更新对象的具体实现就不多啰嗦了,相信大家都会了,但是有一点需要提出的是,在update的时候,需要判断TypeBase.ValueChanged==true的时候,才做数据更行,否则不做处理,这样才能够达到文章题目的差异数据保存
}

// 删除对象
public   bool  Delete()
{
    
// very easy.
    
// DELETE FROM TableName WHERE ID = ID....
}

 看完代码,大家可能会有很多疑问,莫非每个对象都要写这么几个Save(), Insert(), Update(), Delete()方法,那岂不是比写sql语句还要累,或许你现在还会这么讲,但是相信凭你神一般的抽象能力,我想在一又三分子一秒之后,你肯定一拍脑袋,把数据库实体类抽象出来,然后把这几个方法放在基类中不久一切ok了吗,如果能想到这里,小虾只能说:哎,知音啊!

 

讲到这里,小虾的0查询语句就基本上是讲完了,或许你会说还有个查询语句没讲呢,小虾想说的是,查询功能就像打太极,几乎是千变万化, 无所不有,无坚不摧, 无...这些我就留到小虾接下来的文章中讲解。

 

接下来的文章可能包括:

1.自定义数据库实体类之基类抽象——ObjBase对象搭建

可能提供方法有:Save();Delete();DeleteById();GetListObject<T>(param1...);

2、自定义数据库实体类之查询语句对象——QueryString对象的实现

QueryString对象:类似Linq的数据库查询语句的写法,但是写法又更简单,更舒服,更。。。。请大家期待。

可能出现的语法有:QueryString.Select(...).From(...).Where(new Condition().And().Or()..).And().OrderBy();

 

 

ASP.NET开发技术交流群: 67511751(人员招募中...)

posted on 2011-05-24 11:47 Juvy 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/Juvy/archive/2011/05/24/2055228.html

内容概要:该研究通过在黑龙江省某示范村进行24小时实地测试,比较了燃煤炉具与自动/手动进料生物质炉具的污染物排放特征。结果显示,生物质炉具相比燃煤炉具显著降低了PM2.5、CO和SO2的排放(自动进料分别降低41.2%、54.3%、40.0%;手动进料降低35.3%、22.1%、20.0%),但NOx排放未降低甚至有所增加。研究还发现,经济性和便利性是影响生物质炉具推广的重要因素。该研究不仅提供了实际排放数据支持,还通过Python代码详细复现了排放特征比较、减排效果计算和结果可视化,进一步探讨了燃料性质、动态排放特征、碳平衡计算以及政策建议。 适合人群:从事环境科学研究的学者、政府环保部门工作人员、能源政策制定者、关注农村能源转型的社会人士。 使用场景及目标:①评估生物质炉具在农村地区的推广潜力;②为政策制定者提供科学依据,优化补贴政策;③帮助研究人员深入了解生物质炉具的排放特征和技术改进方向;④为企业研发更高效的生物质炉具提供参考。 其他说明:该研究通过大量数据分析和模拟,揭示了生物质炉具在实际应用中的优点和挑战,特别是NOx排放增加的问题。研究还提出了多项具体的技术改进方向和政策建议,如优化进料方式、提高热效率、建设本地颗粒厂等,为生物质炉具的广泛推广提供了可行路径。此外,研究还开发了一个智能政策建议生成系统,可以根据不同地区的特征定制化生成政策建议,为农村能源转型提供了有力支持
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值