.NET Tech Blog - Find Web Hosting

Find best web hosting with coupon, professional editorial reviews and customer voted reviews.

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

开发中的DataQuicker

DataQuicker是一款O/R Mapping工具,意在完成实体层开发的智能化。我们知道,在大部分的系统中,我们都会投入大量的时间和人力来进行实体层编码,包括SQL拼写、数据有效性检查以及实体层的设计等,硬编码的SQL或者使用存储过程会在一定提高应用程序的性能,但是却使程序和数据库的耦合性上升,使后期维护或者中期的变更变成一场灾难。

 

市面上有很多的ORM,我有研究过NHiberateGentle.NET。对于NHiberate,它的使用相对麻烦,并且当我在实体层的使用时上减小工作量的,同时Domain Modal的设计却会花费我们的大量时间,并且钻研NHiberate也花费我们很多的时间,在我以前的公司里,一个JAVA Team的伙计就经常发呆般的看着白板思考如何设计Domain。对于Gentle.NET,我个人认为它相对简单,这里是说它能够完成的功能,以及在数据库-应用程序之间的映射上。当然,我这里不是说他们不好,只是适合与否而已。

 

DataQuicker相对于Gentle是一款更加OOORM,它不仅考虑表实体,它同时封装了字段,不同的数据库字段类型对应DataQuickerFieldMapping字段抽象类的派生类,比如text-FStringint-FIntdecimal-FDecimal。这样,在系统初始化时,DQ首先会得到数据库的结构Schema,每个表实体的字段对象对应数据库中的字段,它们也会保存表字段的Schema,比如长度、默认值甚至自自己的正则表达式,以便我们在操作中,凡是遇到不合法的输入,它可以不与数据库通信即检查数据的有效性

 

DataQuicker的实体层设计非常简单,因为它使用了Aspect#,只需要罗列出表、字段、关联表即可。如示例代码:

using System;

using DataQuicker.Framework;

 

namespace DataQuicker.UnitTest

{

       //Entity属性指定该实体映射的表/试图名称

       // Provider属性制定该表对应的DataBaseDataQuicker允许在多个不同数据库连接的支持,比如两个SQL数据库的连接,
    //一个是
DB1,另一个是DB2。这里,对于DB1/2的定义是在配置文件中进行的

       [Entity("reply_message"), Serializable, Provider("DB1")]

       public class MessageDetail: TableMapping

       {

              public MessageDetail(){}

 

              //标注该字段映射的数据库中字段的名称,FPrimaryKey说明该字段是PrimaryKey

              [Field("identity")]

              public virtual FPrimaryKey ID

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("datetime"), Alias("reply_datetime")]

              public virtual FDateTime ReplyDateTime

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("author")]

              public virtual FString Author

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("reply_message")]

              public virtual FString ReplyMessage

              {

                     get

                     {

                            return null;

                     }

              }

 

              //这里是一个关联表,message_ref_id是指当前Detail表中的外键,而Alias("master_message")指定关联的Header在当前字体中将使用表别名

              [Association("message_ref_id"), Alias("master_message")]

              public virtual MessageHeader MessageHeader

              {

                     get

                     {

                            return null;

                     }

              }

 

              //构造对象,DataQuicker中将不使用实体类的构造函数构造对象,而使用静态的CreateInstance方法,每个实体类需要实现该方法

              public static MessageDetail CreateInstance()

              {

                     return PersistenceBuilder.Instance.CreateInstance(typeof(MessageDetail)) as MessageDetail;

              }

       }

}

 

using System;

using DataQuicker.Framework;

 

namespace DataQuicker.UnitTest

{

       /// <summary>

       ///这里是上示例中关联的MessageHeader表的定义

       /// </summary>

       [Entity("message"), Serializable, Provider("DB1")]

       public class MessageHeader: TableMapping

       {

              public MessageHeader()

              {

              }

 

              [Field("identity")]

              public virtual FPrimaryKey ID

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("author")]

              public virtual FString Author

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("subject")]

              public virtual FString Subject

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("message")]

              public virtual FString Message

              {

                     get

                     {

                            return null;

                     }

              }

 

              [Field("datetime"), Alias("create_datetime")]

              public virtual FDateTime CreateDateTime

              {

                     get

                     {

                            return null;

                     }

              }

 

              public static MessageHeader CreateInstance()

              {

                     return PersistenceBuilder.Instance.CreateInstance(typeof(MessageHeader)) as MessageHeader;

              }

       }

}

 

通过以上的代码,实体层就设计好了,以下演示我在NUnit中的调用,

[Test]

public void TestSelect()

{

       MessageDetail detail = MessageDetail.CreateInstance();

       detail.MessageHeader.Author.SetCondition("Eunge");

       detail.MessageHeader.Subject.SetCondition("DataQuicker");

       detail.AddOrderBy(detail.MessageHeader.Subject);

       // SQLAnalyzer只是一个内置的SQLServer语句分析器,其他还是JetOracle等,在实际中,应该是直接调用detail.Select()得到查询结果。这里 
   //只是为了演示分析出的查询语句

SQLAnalyzer analyzer = new SQLAnalyzer();

       string strSQL = this.analyzer.Select(detail, new FieldMapping[]{detail.ID, detail.MessageHeader.Subject}, true, 100);

       string strExpect = "SELECT DISTINCT TOP 100 reply_message.[identity], master_message.subject FROM reply_message JOIN message master_message ON reply_message.message_ref_id=master_message.[identity] WHERE (master_message.subject = 'DataQuicker') AND (master_message.author = 'Eunge') ORDER BY master_message.subject";

        Assert.AreEqual(strExpect, strSQL);

}

 

DataQuicker是我第一个Test-Driven驱动的项目,其实由于个人对TD还不能完全掌握,只是在一种揣摩中进行了DataQuicker的开发,现在开发还在进行,最迟3个月内能与广大朋友见面。

 

到时候还请多多支持和关注才是。

posted on 2005-07-01 13:26  Eunge  阅读(3308)  评论(8编辑  收藏  举报