Grove——.NET中的ORM實現

?

Grove——.NET中的ORM實現

發布日期: 6/30/2005 | 更新日期: 6/30/2005

作者:林學鵬

ORM的全稱是Object Relational Mapping,即對象關系映射。它的實質就是將關系數據(庫)中的業務數據用對象的形式表示出來,并通過面向對象(Object-Oriented)的方式將這些對象組織起來,實現系統業務邏輯的過程。在ORM過程中最重要的概念是映射(Mapping),通過這種映射可以使業務對象與數據庫分離。從面向對象來說,數據庫不應該和業務邏輯綁定到一起,ORM則起到這樣的分離作用,使數據庫層透明,開發人員真正的面向對象。圖 1簡單說明了ORM在多層系統架構中的這個作用。

art\grove_001.jpg

圖1:ORM在多層系統架構中的作用

目前大多數項目或產品都使用關系型數據庫實現業務數據的存儲,這樣在開發過程中,常常有一些業務邏輯需要直接用寫SQL語句實現,但這樣開發的結果是:遍地布滿SQL語句。這些高藕合的SQL語句給系統的改造和升級帶來很多無法預計的障礙。為了提高項目的靈活性,特別是快速開發,ORM是一個不錯的選擇。舉個簡單的例子:在使用ORM的系統中,當數據庫模型改變時,不再需要理會邏輯代碼和SQL語句中涉及到該模型的所有改動,只需要將該模型映射的對象稍作改動,甚至不做改動就可以滿足要求。

一、ORM的工具實現:Grove

優秀的ORM工具不僅可以幫助我們很好的理解對象及對象的關系,而且工具本身會幫助我們維護這些關系。基于這個理念,我設計了基于.NET的ORM工具——Grove ORM Development Toolkit。

Grove ORM Development Toolkit包含Grove和Toolkit兩部分內容。Grove為ORM提供對象持久、關系對象查詢、簡單事務處理、簡單異常管理等功能。數據持久包括一些對象的Insert、Delete、Update、Retrieve等功能,關系對象查詢則提供一些基于對象的復雜關系查詢,包括對應到數據庫功能的子查詢、關聯查詢(JOIN)、函數支持(count、avg、max、min)、聚合等。Toolkit是基于VS.NET 2002/2003的VSIP開發的外接程序,職責是幫助開發人員快速映射關系數據庫中的業務模型到符合Grove要求的映射實體類,以及映射數據庫中復雜關系查詢到Grove要求的關系映射實體,暫時只提供C#支持。圖 2是Grove內部類實現關系圖。

art\grove_002.jpg

圖 2: Grove內部類實現關系圖

在ORM實現的前期工作中,為了實現屏蔽各種數據庫之間的操作差異,我們需要定義數據操作公有接口,封裝基本的數據庫Insert,Update,Delete,Query等操作。

public interface IDbOperator
{
int ExecNonQuery(string cmdText);
int ExecDataSet(string cmdText,DataSet entity); 
object ExecScalar(string cmdText);
…
}

再定義一個數據庫操作工廠類,實現各種不同類型數據的適配。

public abstract class DbOperatorFactory:IDbOperator

然后實現各種數據庫的操作類,以SQLServer為例。

internal class SqlDbOperator:DbOperatorFactory

完成后,就是ORM主角——實體(Entity)的實現。ORM中實體的定義可以通過實體類自身包含數據模型元數據的方式實現,也可以通過定義XML的元描述實現。下面講述了通過實體類自身映射的實現。

實體(Entity)是實際業務數據的載體,包含業務數據模型的元描述,可以直接由數據庫中的某張表或視圖生成,也可以根據需要手工創建。.NET中提供了System.Attribute,該類包含訪問和測試自定義屬性的簡便方法。.NET Framework預定義了一些屬性類型并使用它們控制運行時行為。我們可以通過繼承System.Attribute基類自定義用于描述實體對象映射時所需要的數據模型元數據,包括表名,字段名,字段長度,字段類型等一些常用的數據。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class DataTableAttribute : Attribute

AttributeUsage用來表示該自定義屬性可以被綁定在什么樣的對象上,這里表示應用在Class或者Struct之上。

抽象一些具有相同特征的屬性,使之成為自定義屬性的基類。

[AttributeUsage(AttributeTargets.Property)]
public class BaseFieldAttribute:Attribute

定義一般字段所需要的自定義屬性類。

[AttributeUsage(AttributeTargets.Property)]
public class DataFieldAttribute : BaseFieldAttribute

定義關鍵字字段所需的自定義屬性類。

[AttributeUsage(AttributeTargets.Property)]
public class KeyFieldAttribute : BaseFieldAttribute

定義外鍵字段所需要的自定義屬性類。

[AttributeUsage(AttributeTargets.Property)]
public class ForeignKeyFieldAttribute : BaseFieldAttribute

在以上自定義屬性類完成后,我們需要一個用于訪問實體在運行期綁定的自定義屬性及屬性數據的一個Help類。

internal class TypeHelper

實體定義完成后,我們需要根據實體類中綁定的自定義屬性構造出運行期需要的SQL語句,為了收集實體類定義中的數據結構描述,我們需要定義一個類來說明實體在運行期所引用到的所有關于數據持久的信息,包括關鍵字字段,外鍵字段,一般字段等。

internal class TypeInfo

同時需要一個字段元數據描述類,描述字段在數據庫中的名稱,大小,是否可為空,列類型等信息。

internal class ColumnInfo

以上條件具備后,我們需要定義一個解析類,負責轉換數據的程序類型到數據庫字段類型,并且構造出Insert,Update,Delete,Query等操作所需要的SQL語句。

internal class SqlEntityParser

將上面的操作組合起來就是實體類對象操作員。

public class ObjectOperator

實現新增一個記錄到數據庫中,就是創建了一個新的實體對象,并交由對象操作員進行持久化。

public void Insert(object o)
{
TypeInfo info1=new TypeInfo(o.GetType());//根據實例或者實體描述信息
SQLCommand sc=info1.BuildInsertCommand(o);//構造SQL命令對象
DbOperator.Parameters=sc.Parameters;//賦值SQL命令所需的參數
DbOperator.ExecNonQuery(sc.CommandText);//執行SQL命令
}

這里的SQLCommand對象封裝了SQL命令處理時所需要的一些值,包含SQL語句,命令參數(Parameter)等。

二、Grove在開發中的實際應用

安裝Grove Kit要求Visual Studio 2003 及.NET Framework 1.1支持。從Grove網站下載安裝包之后,解壓縮GroveKit.zip,執行安裝。

在GroveKit安裝結束后,打開VS.NET,在VS.NET的啟動畫面上,您會看到Grove Develop Kit的標志,表示GroveKit已被正確安裝。

2.1生成映射實體類

本文將以C# 項目為例解釋Grove在開發中的具體應用。項目名WebApp1,操作系統 Windows 2000,數據庫SQL Server 2000,數據庫實例名:WebApp1,表結構定義如下:

表名字段

Customers

CustomerID int(4) PK

CustomerName varchar(50)

CustomerDesc varchar(200)

Status tinyint

Addresses

AddressID int(4) PK

CustomerID int(4) FK

Address varchar(200)

1.

在VS.NET中,打開“文件->新建->項目”,在Visual C#項目選擇ASP.NET WEB應用程序,確定后生成WebApp1項目,在項目中添加對Grove.dll的引用,Grove.dll位于GroveKit的安裝路徑下,您也可以通過.NET Configuration將Grove添加到程序集緩存中。

2.

在VS.NET中,打開“工具->Grove Tool Kit”,在GroveToolKit中設置數據庫連接屬性,并保存。

art\grove_003.jpg

圖3 設置數據庫連接串

3.

配置當前Web項目的web.config(在</configuration>之前加入以下配置)

<appSettings>
<add key="DBConnString" value="Server=localhost;Uid=sa;Pwd=sa;Database=WebApp1" />
</appSettings>

4.

4)在VS.NET解決方案資源管理器中選中Entities,并在GroveToolKit中選擇表名,點擊GroveToolKit的toolbar中的Preview Entity Class按鈕,出現該表的實體映射類預覽窗口。

art\grove_004.jpg

圖4 預覽實體映射類

5.

檢查當前預覽的實體類,點擊生成文件按鈕,該實體類將被生成到解決方案資源管理器當前選中的路徑下。

6.

重復4,5步驟就可以生成其他表的映射實體類。

Customer.cs
using System;
using Grove.ORM;
[DataTable("Customers")]
public class Customer
{
int _CustomerID;
string _CustomerName;
string _CustomerDesc;
int _Status;[KeyField("CustomerID")]
public int CustomerID
{
get{return this._CustomerID;}
set{this._CustomerID=value;}
}
[DataField("CustomerName")]
public string CustomerName
{
get{return this._CustomerName;}
set{this._CustomerName=value;}
}
[DataField("CustomerDesc")]
public string CustomerDesc
{
get{return this._CustomerDesc;}
set{this._CustomerDesc=value;}
}
[DataField("Status")]
public int Status
{
get{return this._ Status;}
set{this._ Status=value;}
}
}
Address.cs
using System;
using Grove.ORM;
[DataTable("Addresses")]
public class Address
{
int _AddressID;
int _CustomerID;
string _Address;[KeyField("AddressID")]
public int AddressID
{
get{return this._AddressID;}
set{this._AddressID=value;}
}
[ForeignKeyField("CustomerID")]
public int CustomerID
{
get{return this._CustomerID;}
set{this._CustomerID=value;}
}
[DataField("Address")]
public string CustomerAddress
{
get{return this._Address;}
set{this._Address=value;}
}
}

代碼1.實體映射類

2.2對象持久化

Grove提供ObjectOperator實現對映射實體對象的數據庫持久工作,并通過IObjectQuery接口實現對復雜數據庫關系映射實體的查詢,主要接口如下:

方法說明

Insert

新增一個對象

Update

根據條件更新一個對象

Remove

根據條件刪除一個對象

RemoveChilds

刪除所有關系對象

Retrieve

返回一個對象

RetrieveChilds

返回所有關系對象

GetDataReader

返回IDataReader

GetObjectSet

返回對象集合

GetObjectSource

根據對象定義返回DataSet

GetCount

從數據源返回記錄條數

BeginTranscation

在數據庫支持事務的基礎上,開始事務處理

Commit

完成當前事務

Rollback

回退當前事務

2.3數據查詢

如一般的關系型數據庫所具有的查詢功能一樣,Grove也有著非常豐富的查詢功能,如對象查詢、函數查詢、子查詢、排序查詢等。這里對對象查詢做簡單介紹,其它查詢讀者可以自行參考Grove的開發文檔。Grove提供ObjectQuery 幫助ObjectOperator從數據源查詢數據, ObjectOperator 需要通過ObjectQuery解析實體對象中的屬性(System.Arrtibute)定義,并構造查詢語句。ObjectQuery在運行時往往需要定義篩選語句(請參考篩選語句的語法定義)。例如,檢索Customer對象,當State 屬性等于WA的情況:

ObjectQuery query=new ObjectQuery(typeof(Customer),"this.State='WA'");

當檢索需要返回所有對象時,則不需要定義篩選語句

ObjectQuery query=new ObjectQuery(typeof(Customer),"");

2.4篩選語句的語法定義

在ObjectQuery中使用的篩選允許你在定義的時候,根據使用面向對象語法規則進行定義篩選語句。

操作描述

!, not

用于比較布爾型,例如:

!Order.CustomerID.Contains(Customer.CustomerID)

<, >, <= , >=

用于值比較,例如:

Order.Quantity >= 12

=, !=, <>, = =

用于值判斷,例如:

Customer.Country = 'USA' and Customer.Region != 'WA'

and, &&

用于邏輯判斷,例如:

Customer.Country = 'USA' and Customer.Region = 'WA'

or, ||

用于邏輯判斷,例如:

Customer.LastName = 'Smith' or Customer.LastName = 'Jones'

?

三、總結

以上就是ORM的簡單實現,復雜的關系對象映射及關系映射實體的查詢也是ORM中尤為重要的一塊處理,為了屏蔽各數據庫之間的SQL差異,很多好的ORM框架都提供一種符合面向對象語言本身語法規則的Query Language支持,例如實現對數據庫函數的支持時,會通過定義一些公開的,與編程語言接近的語言來實現,比如說定義Object.Size(),Object.Sum()等類方法式操作語法,在邏輯判斷的時候提供一些語言本身的邏輯運算符支持,比如c#中的&&表示and,||表示or等等這些一系列的面向對象編程風格的支持,都很好地為基于關系型數據庫支持的系統開發向“面向對象”提供了有力的支持。Grove目前對關系對象查詢有很好的支持,感興趣可以到Grove的網站了解詳細信息。

注:關于Grove的詳細信息和安裝包,支持站點已經提供了一些相關幫助和下載。http://grove.91link.com

轉載于:https://www.cnblogs.com/ipointer/archive/2005/07/27/201242.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277306.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277306.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277306.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

let和const

發布自Kindem的博客&#xff0c;歡迎大家轉載&#xff0c;但是要注意注明出處。另外&#xff0c;該文章收納在Kindem的個人的 IT 知識整理倉庫&#xff0c;歡迎 Star、Fork、投稿 let let是在ES6加入的新的變量聲明方法&#xff0c;let聲明變量的方法和var類似: let a hello; …

GIT 操作筆記

設置不用每次都輸入 賬號密碼 git config --global credential.helper store然后&#xff0c;下次再輸入一次 賬號密碼 就可以了。刪除github上的文件$ git pull origin master 將遠程倉庫里面的項目拉下來$ dir 查看有哪些文件夾$ git rm -r --cached target 刪除target文件…

[book]道法自然

前不久讀了王詠剛的〈凌波微步〉和〈凌波微步II〉&#xff0c;感覺不錯。今天把他老人家的《道法自然》也買了下來。在dearbook看到關于這本書的長篇大評&#xff0c;也一塊copy了下來&#xff1a;http://www.dearbook.com.cn/book/viewbook.aspx?pnoTS0023954認真的作者&…

c語言編手機藍牙軟件的代碼,51單片機C語言的簡易藍牙鎖代碼

#include#define uint unsigned int#define uchar unsigned charuchar r_buf; //藍牙接收到的字符存儲緩沖區sbit PWMAP2^0; //電機驅動模塊接口sbit IN1P2^2;sbit IN2P2^1;sbit STBYP2^3;sbit LED1P0^0; //LED燈接口sbit LED2P0^1;sbit LED3P0^2;sbit key1P1^0;…

列表嵌套字典,根據字典某一key排序

在返回列表嵌套字典時候&#xff0c;往往需要對數據進行一定的處理&#xff1a;按照字典中某一個key排序 In [87]: a [{"name": "牛郎", "age": 23},{"name":"許仙", "age": 20},{"name":"董永&q…

display: inline-block 布局

三個元素display: inline-block; 布局 &#xff0c;其中一個元素中存在其他元素也用了display: inline-block; 無法垂直居中&#xff0c;將這個元素設置為display: inline; 轉載于:https://www.cnblogs.com/Running00/p/11163751.html

GCC精彩之旅

在為Linux開發應用程序時&#xff0c;絕大多數情況下使用的都是C語言&#xff0c;因此幾乎每一位Linux程序員面臨的首要問題都是如何靈活運用C編譯器。目前 Linux下最常用的C語言編譯器是GCC&#xff08;GNU Compiler Collection&#xff09;&#xff0c;它是GNU項目中符合ANSI…

寫出C語言中5種數據類型的名稱及其關鍵字,求C語言中的32個關鍵字及其意思?...

關鍵字如下&#xff1a;一、數據類型關鍵字(12個)&#xff1a;(1) char &#xff1a;聲明字符型變量或函數(2) double &#xff1a;聲明雙精度變量或函數(3) enum &#xff1a;聲明枚舉類型(4) float&#xff1a;聲明浮點型變量或函數(5) int&#xff1a; 聲明整型變量或函數(6…

想要設計自己的微服務?看這篇文章就對了

歡迎大家前往騰訊云社區&#xff0c;獲取更多騰訊海量技術實踐干貨哦~ 本文由我就靜靜地看 發表于云社區專欄 本文通過使用Spring Boot&#xff0c;Spring Cloud和Docker構建的概念驗證應用程序的示例&#xff0c;為了解常見的微服務架構模式提供了一個起點。 該代碼在Github上…

函數的嵌套調用

在函數的內部調用其他的函數 def index(): func() print("index") def func(): index() # def index():# func()# print("index")## def func():# print("func")# index()#def my_max(x,y): #這個函數的作用就是比大小誰大打印出…

mysql 開發進階篇系列 41 mysql日志之慢查詢日志

一.概述 慢查詢日志記錄了所有的超過sql語句( 超時參數long_query_time單位 秒&#xff09;&#xff0c;獲得表鎖定的時間不算作執行時間。慢日志默認寫入到參數datadir(數據目錄)指定的路徑下。默認文件名是[hostname]_slow.log&#xff0c;默認超時是10秒&#xff0c;默認不開…

分數相同名次排名規則C語言,如何給數據排名(相同分數相同名次)-excel篇

使用Rank函數來做數據排名該函數是返回一個數值在一個數字列表中的排名。語法&#xff1a;RANK(number,ref,order)RANK(對象,范圍,參數)number(必填參數):是特定單位格中的數據&#xff0c;需要在整個數字列表中排名的單個對象。ref(必填參數):是指需要排名的整體數列。即范圍&…

子窗體列表在菜單中的實現

想在菜單中加入子窗體的列表&#xff0c;上網找了半天&#xff0c;都很麻煩&#xff0c;后來看看了菜單的屬性&#xff0c;發現里面有個MdiList屬性&#xff0c;設置成true&#xff0c;搞定&#xff0c;暈。 轉載于:https://www.cnblogs.com/catzhou/articles/258450.html

MySql的連接查詢

若一個查詢同時涉及到兩個或者兩個以上的表&#xff0c;則稱之為連接查詢。常見的包括&#xff1a;等值連接查詢&#xff0c;自然連接查詢&#xff0c;非等值連接查詢&#xff0c;自身連接查詢&#xff0c;外連接查詢&#xff08;左右連接&#xff09;。 1.等值與非等值連接查詢…

linux下ssh通過公鑰登錄服務器

經常會通過ssh登錄遠程服務器&#xff0c;一種是通過密碼方式登錄&#xff0c;一種是通過公鑰登錄。 如何設置通過公鑰登錄服務器 1. 首先生成自己的公鑰和私鑰 ssh-keygen 命令用來生成公鑰和私鑰-t 用來指定密鑰類型&#xff08;dsa | ecdsa | ed25519 | rsa | rsa1&#xff…

qt運行C語言后無顯示,qt designer啟動后不顯示界面問題的原因與解決辦法-站長資訊中心...

Qt 5.6.1無論是在vs里雙擊ui文件還是直接啟動designer.exe都一直無法顯示界面&#xff0c;但任務管理器中可以看到該進程是存在的。前幾天還正常的&#xff0c;但昨天加了一塊NVIDIA的顯卡(機器自帶核顯)&#xff0c;可能與此有關。幸好還可以通過QtCreator打開ui文件進行編輯。…

OpenSolaris北京用戶組的第一次活動

OpenSolaris北京用戶組的第一次活動作者: BadcoffeeEmail: blog.olivergmail.comBlog: http://blog.csdn.net/yayong2005年10月10月15號&#xff0c;OpenSolaris北京用戶組在北京西郊賓館會議廳組織了成立以來的第一次活動。盡管OpenSolaris早在2005年6月14日就正式開放源代碼&…

. SQL多條件查詢存儲過程

編輯器加SQL多條件查詢存儲過程 2010-05-13 17:06:29| 分類&#xff1a; SQL | 標簽&#xff1a; |字號大中小 訂閱 . 例一、 ALTER proc SelectProduct ProdID varchar(10), ProdName nvarchar(30), CategoryID varchar(5), MinPrice decimal(10,2), MaxPrice decimal(10,2) a…

矩陣轉置c語言的思路,矩陣轉置 (C語言代碼)

解題思路:注意事項:參考代碼:#includeint main(){int n,s[100][100];void transposition(int(*p)[100], int n);scanf("%d", &n);for (int i 0; i < n; i){for (int j 0; j < n; j)scanf("%d", *(s i) j);}transposition(s, n);return 0;}vo…

Android PermissionUtils:運行時權限工具類及申請權限的正確姿勢

Android PermissionUtils&#xff1a;運行時權限工具類及申請權限的正確姿勢 ifadai 關注 2017.06.16 16:22* 字數 318 閱讀 3637評論 1喜歡 6PermissionUtil 經常寫Android運行時權限申請代碼&#xff0c;每次都是復制過來之后&#xff0c;改一下權限字符串就用&#xff0c;把…