Gentle.NET 使用文檔

 《原文地址:http://www.cnblogs.com/surfsky/archive/2007/04/05/438762.html#700591

------------------------------------------------------------
概述
------------------------------------------------------------
介紹
    Gentle.NET是一個開源的優秀O/R Mapping的對象持久化框架。介紹就不多說了,以下是原文:
    Gentle.NET is an RDBMS independent object persistence framework. It features automatic SQL generation and object construction, and SQL factory for creating custom queries, DataView construction helpers, excellent performance and reasonably complete docs.
    Gentle.NET是一個關係數據庫中立的(RDBMS indenpendent)對象持久化框架。它具有以下特徵:
        ·自動構建SQL
        ·自動創建實體對象
        ·用於創建定製查詢的SQL工廠
        ·DataView創建助手
        ·優秀的性能
        ·合理完善的文檔

相關資源
    官方首頁:http://www.mertner.com/confluence/display/Gentle/Home
    開發團隊:http://www.mertner.com/confluence/display/Gentle/Project+Team
    最新文檔:http://www.mertner.com/confluence/display/Gentle/Documentation+Home
    開發進度:http://www.mertner.com/jira/browse/GOPF
    例程下載:http://www.mertner.com/confluence/display/Gentle/Sample+Projects
    開發計劃:http://www.mertner.com/confluence/display/Gentle/Open+Tasks
    OR映射:  http://www.15seconds.com/issue/040112.htm
   
最新版本
    1.2.9  2006-06

安裝包中(1.2.9)的內容
    Build/
        Nant編譯文件,強名密鑰文件,NDoc文檔生成文件等
    Configuration/
        App.config和Gentle.Config配置文件,這兩個文件差不多,只是app.config多了個log4net配置節
        App.config配置文件要根據情況改成web.config
        Gentle.Config只要放到與項目編譯生成程序集相同的目錄下就行了,組件自己會去搜尋這個配置文件
        只要使用一個就可以
    Contributions/
        MyGeneration和CodeSmith的代碼生成模板
    Documentation/
        幫助文檔。
        Gentle API.chm:GentleAPI介紹文檔。估計也是用工具自動生成的。
        GentleDocumentation.pdf:順序混亂使用文檔,最好根據左側的目錄樹來導航。該文件中的UserGuide部分要好好看看
    Output/
        dll文件。裏面存放的是已經編譯的好的程序集(Release版),可以直接拷出來使用
    Source/
        gentle源代碼
        Gentle.Framework.Tests/  測試例程

Gentle 2.*開發計劃
    Morten Mertner對gentle的發展方向非常明確,並提出了野心勃勃的2.x版本開發計劃(http://www.mertner.com/confluence/display/gentle/open+tasks),着重於提高gentle的使用便利性。大致瀏覽了一下,以下功能我頗感興趣:
        擴展日誌模塊,允許使用自定義的日誌記錄器
        查詢方面的增強
            ·所有查詢對象和查詢結果都可序列化
            ·添加分頁支持
            ·增強對關係查詢(joins)的支持
            ·添加lazy load功能
            ·添加創建/刪除表的支持
            ·添加OPath功能(用於對象查詢,類似ibastic的HQL)
         VisualStudio插件
            ·可查找Gentle類
            ·創建gentle包裝代碼
            ·直接在VS中創建相應的數據庫表
            ·擴展類設計器,允許使用Gentle attribute來修飾類
       
       

------------------------------------------------------------
使用
------------------------------------------------------------
1.加入Gentle.Net程序集引用
    Gentle.Common.dll
    Gentle.Framework.dll
    Gentle.Provider.*.dll
2.修改gentle配置文件
    (1)修改Gentle.config文件中的<DefaultProvider>和<Providers>部分
    (2)把Gentle.Config拷貝到項目內
        ·項目根目錄下
        ·項目子目錄config下
        ·任意位置。需要在web.config中指明gentle配置文件路徑<add key="GentleConfigFolder" value="./Gentle2.config"/>
3.創建數據庫表和視圖
4.使用代碼工具CodeSmith或MyGeneration等生成Gentle類文件
5.使用這些類。這些類提供了基本的選取和修改的功能,可手動修改該文件以滿足自定義功能

------------------------------------------------------------
MyGeneration生成的gentle類代碼示例
------------------------------------------------------------
以留言簿數據表的gentle類包裝爲例:
(1)留言簿的數據字典
    id          自增數字字段
    name        字符串
    email       字符串
    web         字符串
    ip          字符串
    title       字符串
    content     字符串
    createDate  時間日期
(2)MyGeneration生成的包裝類。代碼非常緊湊幹練,排版風格我也很喜歡:>。
    [TableName("GuestBook", CacheStrategy.Temporary)]
    public class GuestBook : Persistent
    {
        #region Members
        private bool isChanged;
        [TableColumn("id", NotNull=true), PrimaryKey(AutoGenerated=true)]
        protected int id;
        [TableColumn("name", NullValue="")]
        protected string name;
        [TableColumn("email", NullValue="")]
        protected string email;
        [TableColumn("web", NullValue="")]
        protected string web;
        [TableColumn("ip", NullValue="")]
        protected string ip;
        [TableColumn("title", NullValue="")]
        protected string title;
        [TableColumn("content", NullValue="")]
        protected string content;
        [TableColumn("createDate")]
        protected DateTime createDate;
        #endregion
           
        #region Constructors
        /// <summary>
        /// Create a new object using the minimum required information (all not-null fields except
        /// auto-generated primary keys).
        /// </summary>
        public GuestBook()
        {
            isChanged = true;
            id = 0;
        }
   
        /// <summary>
        /// Create a new object by specifying all fields (except the auto-generated primary key field).
        /// </summary>
        public GuestBook(string name, string email, string web, string ip, string title, string content, DateTime createDate)
        {
            isChanged = true;
            this.name = name;
            this.email = email;
            this.web = web;
            this.ip = ip;
            this.title = title;
            this.content = content;
            this.createDate = createDate;
        }
           
        /// <summary>
        /// Create an object from an existing row of data. This will be used by Gentle to
        /// construct objects from retrieved rows.
        /// </summary>
        public GuestBook(int id, string name, string email, string web, string ip, string title, string content, DateTime createDate)
        {
            this.id = id;
            this.name = name;
            this.email = email;
            this.web = web;
            this.ip = ip;
            this.title = title;
            this.content = content;
            this.createDate = createDate;
        }
        #endregion
   
        #region Public Properties
        public bool IsChanged
        {
            get    { return isChanged; }
        }
   
        /// <summary>
        /// Property relating to database column id
        /// </summary>
        public int Id
        {
            get { return id; }
        }
   
        /// <summary>
        /// Property relating to database column name
        /// </summary>
        public string Name
        {
            get { return name; }
            set { isChanged |= name != value; name = value; }
        }
   
        /// <summary>
        /// Property relating to database column email
        /// </summary>
        public string Email
        {
            get { return email; }
            set { isChanged |= email != value; email = value; }
        }
   
        /// <summary>
        /// Property relating to database column web
        /// </summary>
        public string Web
        {
            get { return web; }
            set { isChanged |= web != value; web = value; }
        }
   
        /// <summary>
        /// Property relating to database column ip
        /// </summary>
        public string Ip
        {
            get { return ip; }
            set { isChanged |= ip != value; ip = value; }
        }
   
        /// <summary>
        /// Property relating to database column title
        /// </summary>
        public string Title
        {
            get { return title; }
            set { isChanged |= title != value; title = value; }
        }
   
        /// <summary>
        /// Property relating to database column content
        /// </summary>
        public string Content
        {
            get { return content; }
            set { isChanged |= content != value; content = value; }
        }
   
        /// <summary>
        /// Property relating to database column createDate
        /// </summary>
        public DateTime CreateDate
        {
            get { return createDate; }
            set { isChanged |= createDate != value; createDate = value; }
        }
        #endregion
   
        #region Storage and Retrieval
   
        /// <summary>
        /// Static method to retrieve all instances that are stored in the database in one call
        /// </summary>
        static public IList ListAll()
        {
            return Broker.RetrieveList(typeof(GuestBook));
        }
   
        public static GuestBook Retrieve(int id)
        {
            Key key = new Key(typeof(GuestBook), true, "id", id);
            return Broker.RetrieveInstance(typeof(GuestBook), key) as GuestBook;
        }
       
        public static GuestBook ComplexRetrieve(int id)
        {
            throw new NotImplementedException("Gentle.NET Business Entity script: Generation of complex retrieve function (multiple primary keys) is not implemented yet.");
            //return null;
        }
       
        public override void Persist()
        {
            if (IsChanged || !IsPersisted)
            {
                base.Persist();
                isChanged = false;
            }
        }
   
        public override void Remove()
        {
            base.Remove();
        }
        #endregion
    }
(3)如上,該類實現了基本的CRUD操作
    增:GuestBook entity = new GuestBook(...); entity.Persist();
    查:GuestBook entity = GuestBook.Retrieve(id); 或 IList list = GuestBook.RetrieveAll();
    改:GuestBook entity = GuestBook.Retrieve(id); ...; entity.Persist();
    刪:GuestBook.Retrieve(id).Remove;
(4)擴展該類
    ·默認的刪除函數效率比較低下,建議創建靜態函數
        public static void Remove(int id)
        {
            Key key = new Key(typeof(GuestBook), true, "id", id);
            Broker.Remove(typeof(GuestBook), key);
        }
        調用時直接用GuestBook.Remove(id)就好了
    ·建議添加PrePersist()和PreRemove()虛函數,方便業務層的擴展,如文件操作,關聯數據表刪除操作等
    ·可參考文章gentle.net bugs fixing

------------------------------------------------------------
例程
------------------------------------------------------------
【新建】
    直接調用Broker.Insert()函數
        Category category = new Category();
        Gentle.Framework.Broker.Insert(category);
    若Category繼承至Persistent類,則直接調用Persist()函數來保存
        Category category = new Category(....);
        category.Persist();

【刪除】
    // e.g. Product.Retrieve(id).Remove();
    public void Remove()
    {
        base.Remove();
    }
    // e.g. Product.Remove(id);
    public static void Remove(int id)
    {
        Key key = new Key(typeof(Product), true, "id", id);
        Broker.Remove(typeof(Product), key);
    }

【查詢】
獲取單條記錄
    // e.g. Category entity = Category.Retrieve(1);
    public static Category Retrieve(int id)
    {
        Key key = new Key(typeof(Category), true, "CategoryID", id);
        return Broker.Retrieve(typeof(Category), key) as Category;
    }

獲取記錄集
    無參數限制
        static public IList ListAll()
        {
            return Broker.RetrieveList( typeof(User) );
        }
    根據一個參數獲取記錄集
        static public IList ListTeamMembers(int teamId)
        {
            Key key = new Key(typeof(Act), true, "teamId", teamId);
            return Broker.RetrieveList(typeof(Member), key);
        }
    根據兩個參數獲取記錄集
        static public IList ListTeamMemberAct(int teamId, int memberId)
        {
            Key key = new Key(typeof(Act), true, "teamId", teamId, "memberId", memberId);
            return Broker.RetrieveList(typeof(Act), key);
        }
    多個參數獲取記錄集
        static public IList ListTeamMemberAct(int teamId, int memberId, int otherId)
        {
            Key key = new Key(typeof(Act), true, "teamId", teamId, "memberId", memberId);
            key.Add("otherId", otherId);
            return Broker.RetrieveList(typeof(Act), key);
        }

SqlBuilder定製查詢(模糊查詢,過濾查詢)
    // 流程:SqlBuilder-->SqlStatement-->SqlResult-->DataView | TypedArrayList
    // 注:particalName必須使用通配符,如"Kev%"
    static public IList ListByNameStartsWith( string partialName )
    {
        SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(User));
        sb.AddConstraint(Operator.Like, "Name", partialName);
        sb.AddConstraint("substr(coalmineid,4,3)='101'");
        sb.AddConstraint("rownum=1");
        sb.AddOrderByField("id");

        SqlStatement stmt = sb.GetStatement(true);
        SqlResult sr = Broker.Execute(stmt);

        return ObjectFactory.GetCollection(typeof(User), sr);
        //return ObjectView.GetDataView(sr);
    }

Criteria語法?
    Criteria criteria = session.createCriteria(TUser.class);
    criteria.add(Expression.eq("groupId", new Integer(2)));
       

返回值類型
    Object
        return Broker.Retrieve(typeof(Category), key) as Category;
    SqlResult
        return Broker.Execute(sql);
        return Broker.Execute(sqlStatement);
    IList(TypeArrayList)
        return Broker.RetrieveList( typeof(User) );
        return Broker.RetrieveList( typeof(User), key );
        TypedArrayList customerList = new TypedArrayList( typeof(Customer) );
        return Broker.RetrieveList( typeof(Customer), customerList );
        return ObjectFactory.GetCollection(typeof(User), sqlResult);
    DataView
        return ObjectView.GetDataView(sqlResult);
    GentleList?

排序
    SqlBuilder排序
        SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(User));
        sb.AddConstraint(Operator.Like, "Name", partialName);
        sb.AddOrderByField("id");
    對TypedArrayList對象排序?
    直接寫SQL的orderby排序?

關聯的實現方案
    public class User
    {
        // 獲取與account相關聯的account對象列表
        public IList Accounts
        {
            get{ return RetrieveList( typeof(Account), "Id" ); }
        }
    }

   
【更新】
    1.最簡單的更新
        User user = User.Retrieve(id);
        user.Name = "Kevin";
        user.Persist();
   
    2.如果想要改變數據的主鍵,就沒有那麼方便了,只能是先刪除-然後改變狀態-然後改變主鍵-最後再插入保存
    private void btnUpdateKey_Click(object sender, System.EventArgs e)
    {
        try
        {
            UT_BM_COALMINE cm=UT_BM_COALMINE.Retrieve("1201010001");
            cm.Remove();
            cm.IsPersisted=false;
            cm.COALMINEID="120101000a";
            cm.Persist();
        }
        catch(GentleException ex)
        {
            if(ex.Error==Gentle.Common.Error.UnexpectedRowCount)
                this.ShowMessage("要更新的數據並不存在!"+ex.Error.ToString ());
            else
                throw;
        }
    }
   
【直接寫sql】
    private SqlResult ExecuteSql(string sql)
    {
        return Broker.Execute(sql);
    }
    private DataView ExecuteSql(string sql)
    {
        SqlResulte sr = Broker.Execute(sql);
        return ObjectView.GetDataView(sr);
    }
    private IList FindUsers(string filter)
    {
        SqlResult sr = Broker.Execute("Select * from User where " + filter);
        return ObjectFactory.GetCollection(typeof(User), sr);
    }

【調用存儲過程: 有點繁雜】
    // GentleSqlFactory
    GentleSqlFactory sqlFact = Broker.GetSqlFactory();

    // IDbCommand & IDataParameter
    IDbCommand cmd = sqlFact.GetCommand();
    cmd.CommandType = CommandType.StoredProcedure;
    IDataParameter param = cmd.CreateParameter();
    param.ParameterName = sqlFact.GetParameterPrefix() + "CustomerId" + sqlFact.GetParameterSuffix();
    param.Value = "ALFKI";
    cmd.Parameters.Add(param);

    // SqlStatement
    SqlStatement sqlStat = new SqlStatement(Gentle.Framework.StatementType.Unknown, cmd, "CustOrderHist");

    // SqlResult
    SqlResult sqlRes = Broker.Execute(sqlStat);
    dataGrid1.DataSource = ObjectView.GetDataView(sqlRes);


【事務處理transaction】
    try
    {
        Transaction transaction = new Transaction();
        transaction.Persist( obj );
        transaction.Commit();
    }
    catch( Exception e )
    {
        transaction.Rollback();
        throw;
    }

【xml序列化】
    public static void SerializeToFile( object obj, string fileName )
    {
        // remove Persistent.IsPersisted attribute
        XmlAttributes attrs = new XmlAttributes();
   
        // create an XML element for IsPersisted
        XmlElementAttribute attr = new XmlElementAttribute();
        attr.ElementName = "IsPersisted";
        attr.Type = typeof(bool);
   
        // add the element to the collection of excluded elements
        attrs.XmlElements.Add( attr );
        attrs.XmlIgnore = true;
   
        // add attribute overrides to hide IsPersisted property of Gentle's Persistent class
        XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
        attrOverrides.Add( typeof(Persistent), "IsPersisted", attrs );
   
        // serialize object
        FileStream fs = new FileStream( fileName, FileMode.Create );
        System.Xml.Serialization.XmlSerializer xml =
            new System.Xml.Serialization.XmlSerializer( obj.GetType(), attrOverrides );
        xml.Serialize( fs, obj );
        ...
    }
   
【對象比較】
    對象是否完全相同(根據hash值)
    public override int GetHashCode()
    {
        PropertyHolder holder = this;
        return holder.Id.GetHashCode() +
            holder.Name.GetHashCode() +
            holder.TInt.GetHashCode() +
            holder.TDecimal.GetHashCode() +
            holder.TDouble.GetHashCode() +
            holder.TBool.GetHashCode() +
            holder.TDateTime.GetHashCode() +
            holder.TDateTimeNN.GetHashCode() +
            // make sure space padding (added by db) is ignored
            holder.TChar.TrimEnd().GetHashCode() +
            holder.TNChar.TrimEnd().GetHashCode() +
            holder.TVarChar.GetHashCode() +
            holder.TNVarChar.GetHashCode() +
            holder.TText.GetHashCode() +
            holder.TNText.GetHashCode();
    }
    public override bool Equals( object obj )
    {
        if( obj.GetType() != this.GetType() )
            return false;

        PropertyHolder holder1 = (PropertyHolder) obj;
        PropertyHolder holder2 = this;
        return holder1.GetHashCode() == holder2.GetHashCode()
            && holder2.GetHashCode() == holder1.GetHashCode();
    }
   

------------------------------------------------------------
【常用的Gentle類】
關於SqlStatement
    存儲Sql語句及相關環境變量
    public SqlStatement( StatementType stmtType, IDbCommand cmd, string sql )
    public SqlStatement(
        PersistenceBroker broker,
        StatementType stmtType, IDbCommand cmd, string sql,
        Type type, int rowLimit, int rowOffset )
    public SqlResult Previous()
        public SqlResult Next()
        public SqlResult Page( int page )


關於SqlBuilder
    用於構造適合特定數據庫類型的SQL語句.可構造的SQL語句類型有
        public enum StatementType
        {
            Unknown,          //
            Select,           // 調用 ExecuteReader()
            Count,            // 調用 ExecuteScalar()
            Identity,         // 調用 ExecuteScalar()
            Insert,           // 調用 ExecuteScalar() 或 ExecuteNonQuery()
            Update,           // 調用 ExecuteNonQuery()
            Delete,           // 調用 ExecuteNonQuery()
            SoftDelete        // 調用 ExecuteNonQuery()
        }
    添加列(構造select語句)
        void AddFields( Type type );                      // 添加所有擁有TableColumn特性的成員
        void AddKeyFields( Type type, bool isParameter ); // 添加所有擁有TableColumn和PrimaryKey特性的成員
    添加約束(用於構造where子句)
        sb.AddConstraint(Operator.Like, "Name", partialName);
        sb.AddConstraint("substr(coalmineid,4,3)='101'");
        sb.AddConstraint("rownum=1");
        public enum Operator
        {
            Equals,
            NotEquals,
            Like,
            NotLike,
            LessThan,
            LessThanOrEquals,
            GreaterThan,
            GreaterThanOrEquals,
            In,
            NotIn
        } ;
    添加排序(order by 子句)
         void AddOrderByField( bool isAscending, string fieldName );
         void AddOrderByField( string orderClause );
    記錄偏移
        void SetRowLimit( int rowLimit )
        void SetRowOffset( int rowOffset )
    構造SQL語句的基本原理(以SQLServer的Select語句構造爲例):
        sql = Format( fmtSelect, GetTopLimit(), AsCommaList( quotedFields ),
                      GetTableName( tableName ), GetConstraints(), GetOrderBy(), "", "" );

關於SqlResult
       /// The SqlResult class serves as a multi-purpose encapsulation of query results,
    /// including access to error codes and information on sql errors, query info
    /// (rows affected/returned), and similar information.
    公共屬性
        public int ErrorCode
        public Exception Error
        public string ErrorMessage
        public int RowsContained
        public int RowsAffected
        public int LastRowId
        public int Count
        public string[] ColumnNames
        public int GetColumnIndex( string columnName )
        public SqlStatement Statement
    數據訪問
        public ArrayList Rows
        public object[] this[ int rowIndex ]
        public object this[ int rowIndex, int columnIndex ]
        public object this[ int rowIndex, string column ]
    分頁處理
        public SqlResult Previous()
        public SqlResult Next()
        public SqlResult Page( int page )
    輔助函數
        public string GetString( int rowIndex, string column )
        public bool GetBoolean( int rowIndex, string column )
        public DateTime GetDateTime( int rowIndex, string column )
        public int GetInt( int rowIndex, string column )
        public long GetLong( int rowIndex, string column )
        public double GetDouble( int rowIndex, string column )
        public decimal GetDecimal( int rowIndex, string column )
        public object GetObject( int rowIndex, string column )
       

------------------------------------------------------------
火花
------------------------------------------------------------
對於非自增且非空字段,gentle自動代碼工具會自動生成倚賴該字段的構造函數,如
    public Account(string account)
    {
        isChanged = true;
        id = 0;
        this.account = account;
    }
   
如何實現join功能
    gentle.net不支持join,但有替代方法
        ·使用視圖
        ·使用GentleList
        ·手工寫SQL: SqlBuilder, SqlStatement
        ·使用QueryDom(http://sourceforge.net/projects/qdom/)
    gentle.net 1.3中將整合進更多改進的查詢功能

如何提升ASP.NET使用gentle的性能
    使用緩存,更改UniqueScope設置(如WebSession)
    儘量關閉Session?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章