Entity Framework學習中級篇

1—EF支持複雜類型的實現

本節,將介紹如何手動構造複雜類型(ComplexType)以及複雜類型的簡單操做。數據庫

一般,複雜類型是指那些由幾個簡單的類型組合而成的類型。好比:一張Customer表,其中有FristName和LastName字段,那麼對應的Customer實體類將會有FristName和LastName這兩個屬性。當咱們想把FirstName和LastName合成一個名爲CustomerName屬性時,此時,若是要在EF中實現這個目的,那麼咱們就須要用到複雜類型。ide

目前,因爲EF不能顯示支持複雜類型,因此咱們沒法在VS裏的可視化設計器裏面來設計咱們須要的複雜類型。因此,咱們須要手動修改實體模型,以便使其支持複雜類型的屬性。修改的主要步驟有如下幾步:函數

l 產生實體模型工具

l 修改CSDL文件性能

l 修改msl文件學習

l 從新生成模型實體類ui

在後續的介紹,我使用數據庫使用的是NorthWind,並針對Customer表對應的實體類來增長複雜屬性Address,其中複雜屬性Address由Address,City,Region,Country和PostalCode這個幾個組合而成。this

下面,介紹具體的操做步驟:spa

第一步:產生實體模型.net

實體模型的產生咱們能夠直接經過在VS可視化設計器來產生(若是不會,請參考《Entity Framework 學習初級篇1--EF基本概況》)。或者使用EdmGen工具來產生(EdmGen工具位於:系統盤符:\WINDOWS\Microsoft.NET\Framework\v3.5下面)。具體步驟就不復述了。

我產生的實體模型文件是:NorthwindEnites.edmx

第二步:修改csdl文件

產生了實體模型後,咱們使用記事本或其餘文本編輯工具打開實體模型,(小技巧:能夠把實體模型後綴.edmx改成.xml ,而後把實體模型文件直接拖到VS裏面進行修改,這樣修改起來比較方便,待修改完畢後,將後綴改回來便可。)

接着,開始手動修改csdl文件,找到模型文件中關於csdl定義的部分,而後找到實體類型名爲Customers的定義節,刪除原來的Address,City,Region,Country,PostalCode屬性定義,而後添加一個名爲Address的屬性.

接着,須要添加一個名爲CommonAddress複雜類型的定義.

至此,csdl部分修改完畢。

第三步,修改msl文件:

找到msl部分的定義,修改Customers部分的影射定義。

至此,msl部分修改完畢

第四步:從新產生實體類文件。

咱們可使用EmdGen2工具來從新實體類.cs文件。具體操做以下:

將修改好的模型文件(edmx),拷貝到使用edmgen2.exe同目錄下,而後在命令行中輸入:

Edmgen2 /codegen cs NorthwindEnites.edmx

執行此命令後,會在當前的文件夾下生成一個NorthwindEnites.cs代碼文件,也就是實體類的代碼文件。將改文件更名爲:NorthwindEnites.Designer.cs(這步主要是和edmx對應起來)。

而後,將NorthwindEnites.edmx和NorthwindEnites.Designer.cs文件添加到項目中。

至此,複合類型的修改完畢。

按照一樣的修改過程,咱們能夠給Employees也增長一個Address的複雜類型屬性。

接下來,咱們看看具體使用代碼:

l 查詢:

[Test]
public void TestAddress()
{
using (var db = new NorthwindModel .NorthwindEntities1())
{
Console.WriteLine("Get Five customer addresss :");
var cts = db.Customers.Take(5);
foreach (var c in cts)
{
Console.WriteLine("Address:{0},Country:{1},City:{2},PostalCode:{3}", c.Address.Address, c.Address.Country, c.Address.City, c.Address.PostalCode);
}
Console.WriteLine("Get Five Employess address:");
var emp = db.Customers.Take(5);
foreach (var c in emp)
{
Console.WriteLine("Address:{0},Country:{1},City:{2},PostalCode:{3}", c.Address.Address, c.Address.Country, c.Address.City, c.Address.PostalCode);
}
}
}

 

l 添加:

[Test]
public void AddTest()
{
using (var db = new NorthwindModel .NorthwindEntities1())
{
var customer = new NorthwindModel .Customers
{
CustomerID = "2009",
CompanyName = "Complex Company",
ContactName = "xray2005",
Address = new NorthwindModel .CommonAddress
{
Address = "SiChuan,China",
City = "ChengDou",
Country = "China",
PostalCode = "610041",
Region = "Chenghua"
}
};
db.AddToCustomers(customer);
db.SaveChanges();
var cst = db.Customers.FirstOrDefault(c => c.CustomerID == "2009");
Assert.IsNotNull (cst);
Console.WriteLine("CustomerID:{0},CompanyName:{1},ContactName:{2},City:{3},Country:{4}", cst.CustomerID, cst.CompanyName, cst.ContactName, cst.Address.City, cst.Address.Country);
}
}

l 條件查詢:

[Test]
public void QueryTest()
{
using (var db = new NorthwindModel .NorthwindEntities1())
{
var cst = db.Customers.FirstOrDefault(c => c.Address.City == "ChengDou");
Assert.IsNotNull (cst);
Console.WriteLine("CustomerID:{0},CompanyName:{1},ContactName:{2},City:{3},Country:{4}", cst.CustomerID, cst.CompanyName, cst.ContactName, cst.Address.City, cst.Address.Country);
}
}

最後,補充說明:

1,在VS的可視化設計器裏,不支持複雜類型,因此修改後沒法再在可視化設計器裏修改模型(edmx文件)。

2,複雜類型不能單獨存在,它必須和某一實體相關起來。

3,複雜類型不能包含導航屬性,如導航到實體或實體集。

4,複雜類型具備內部結構但沒有 Key(主鍵) 屬性的數據類型

 

2—存儲過程(上)

目前,EF對存儲過程的支持並不完善。存在如下問題:

l EF不支持存儲過程返回多表聯合查詢的結果集。

l EF僅支持返回返回某個表的所有字段,以便轉換成對應的實體。沒法支持返回部分字段的狀況。

l 雖然能夠正常導入返回標量值的存儲過程,可是卻沒有爲咱們自動生成相應的實體.cs代碼,咱們仍是沒法在代碼中直接調用或使用標量存儲過程

l EF不能直接支持存儲過程當中Output類型的參數。

l 其餘一些問題。

下面,主要針對如何使用存儲過程,以及存儲返回實體、表的部分字段這個幾個問題,作具體介紹。

l 導入存儲過程及返回實體

在VS可視化設計器中,打開實體模型(emdx文件)。而後,鼠標右鍵點擊「Customers」à 「添加」à「函數導入」,而後選擇「存儲過程名稱」,並輸入函數導入名稱,選擇返回類型爲實體並選擇Customers。以下圖所示:

802x449

以後,點擊「肯定」。以後,存儲過程導入。在代碼咱們就可使用改存儲過程了。以下代碼所示:

[Test]
public void GetEntityBySP()
{
using (var db = new NorthwindEntities())
{
var cst = db.GetCustomerById("ALFKI").FirstOrDefault();
Assert.IsNotNull (cst);
Console.WriteLine("CustomerId:{0},ContactName:{1}", cst.CustomerID, cst.ContactName);
}
}

 

l 聯合查詢結果集的問題

在此版本的EF中,是不支持存儲過程的多張表聯合查詢的,也就是說查詢的結果集中,一部分字段來自表A,另外一部分字段來自表B,像這種狀況,目前EF沒法直接進行處理。爲此,能夠經過寫兩個或多個存儲過程來實現。好比:第一個存儲過程返回表A的全部字段,第二存儲過程返回表B的全部字段;而後,咱們在代碼中來實現聯合的查詢。

按照前面的思路,增長一個返回全部的Orders表字段的存儲過程GetOrdersByCustomerId,再增長一個返回Order Details表所有字段的存儲過程GetDetailsByCustomerId,並將它們導入到實體模型中。

其中,GetOrdersByCustomerId存儲過程以下:

CREATE PROCEDURE GetOrdersByCustomerId
@CustomerId varchar(5)
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM orders WHERE orders.CustomerID=@CustomerId;
END

GetDetailsByCustomerId存儲過程以下:

CREATE PROCEDURE GetDetailsByCustomerId
@CustomerId varchar(5)
AS
BEGIN
SET NOCOUNT ON;
SELECT d.*
FROM  Orders o,[Order Details] d
WHERE o.OrderId=d.OrderId  AND o.CustomerId=@CustomerId;
END

以後,在咱們的代碼來實現聯合查詢。代碼以下:

[Test]
public void GetOrderBySp()
{
using (var db = new NorthwindEntities())
{
var orders = db.GetOrdersByCustomerId("VINET").ToList();
var details = db.GetDetailsByCustomerId("VINET").ToList();
orders.ForEach(o => o.Order_Details.Attach(details.Where(d => d.OrderID == o.OrderID)));
foreach (var order in orders)
{
Console.WriteLine(order.OrderID);
foreach (var d in order.Order_Details)
Console.WriteLine(d.ProductID);
}
}
}

其中,須要注意的,因爲是分別執行了兩個存儲,在內存中是以兩個對立的對象存在,它們以前是沒有創建聯繫的。爲此,咱們須要使用Attach方法來把他們聯繫起來(紅色代碼段),這樣咱們就能夠經過導航來訪問對象的實體了,也就是foreach (var d in order.Order_Details)中的order.Order_Details。

 

l 返回部分字段的問題

默認狀況,目前此版本的EF在使用存儲過程返回實體的時候,必須返回全部的字段,以即是EF可以自動將返回的結果轉換成對應的實體。不然會報「數據讀取器與指定的XXX類型不兼容的異常,….」。

接下來,咱們經過創建一個存儲過程,並創建新創建一個實體來解決此問題。首先,咱們在數據庫中創建一個名爲GetCustomerAndOrders的存儲過程,其定義以下:

CREATE PROCEDURE GetCustomerAndOrders
AS
BEGIN
SET NOCOUNT ON;
SELECT c.CustomerID,c.CompanyName,o.OrderID,o.OrderDate,d.Quantity
FROM Customers c,Orders o,[Order Details] d
WHERE c.CustomerID=o.CustomerID AND o.OrderID=d.OrderID;
END
GO

而後,添加一個實體CustomerOders,並設置屬性以下圖所示:

860x543

而後,在VS可視化設計器中,打開實體模型(emdx文件),經過添加à函數導入,導入存儲過程GetCustomerAndOrders,並取名爲GetCustomerAndOrders,返回類型設置爲實體CustomerOrders。

最後,咱們就能夠代碼實體此實體和存儲過程了。以下代碼:

[Test]
public void GetOrderCountByCustomerId()
{
using (var db = new NorthwindEntities())
{
var co = db.GetCustomerAndOrders().Take(10).Skip(0);
foreach(var c in co)
Console.WriteLine(c.CustomerID);
}
}

 

l 返回標量值問題

目前,EF對存儲過程返回標量值的支持並無徹底。雖然,咱們能夠按照前面的步驟導入函數,並設置返回標量值的類型,同時EF會在實體模型文件爲咱們自動生成此存儲過程相關的映射配置等。可是,EF卻沒有爲咱們生成在實體模型cs文件中,自動生成相應的.cs代碼,因此咱們根本沒法直接調用此存儲過程。爲解決此問題,咱們須要手動添加代碼到實體模型的.cs代碼文件中。

首先,在數據庫中創建存儲存儲過程GetOrderCntByCustomerId,代碼以下:

CREATE PROCEDURE GetOrderCntByCustomerId
@CustomerId varchar(5)
AS
BEGIN
SET NOCOUNT ON;
SELECT count(*) FROM Orders WHERE Orders.CustomerId=@CustomerId;
END

接着,按照正常的步驟,導入此存儲過程並設置返回類型爲標量類型的Int32。

而後,咱們須要添加一個泛型的方法和一個執行存儲過程的方法,代碼以下:

public partial class NorthwindEntities
{
//泛型方法用於執行標量存儲過程
private T ExecuteFunction(string functionName, System.Data.EntityClient.EntityParameter[] parameters) where T : struct
{
System.Data.EntityClient.EntityCommand cmd = ((System.Data.EntityClient.EntityConnection)this.Connection).CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddRange(parameters);
cmd.CommandText = this.DefaultContainerName + "." + functionName;
try
{
if (cmd.Connection.State != System.Data.ConnectionState.Open)
cmd.Connection.Open();
var obj = cmd.ExecuteScalar();
return (T)obj;
}
catch (System.Exception)
{
throw;
}
finally
{
cmd.Connection.Close();
}
}
//執行數據庫中GetOrderCntByCustomerId存儲過程的方法
public int GetOrderCountByCustomerId(string CustomerId)
{
var param = new System.Data.EntityClient.EntityParameter("CustomerId", System.Data.DbType.String);
param.Value = CustomerId;
return ExecuteFunction("GetOrderCountByCustomerId", new[] { param });
}
}

最後,經過以上修改,咱們就能夠直接使用返回標量值的存儲過程,代碼以下:

[Test]
public void GetOrderCountByCustomerId()
{
using (var db = new NorthwindEntities())
{
var result = db.GetOrderCountByCustomerId("VINET");
Assert.Greater(result, 0);
Console.WriteLine(result.ToString());
}
}

至此,咱們就解決了EF存儲過程返回標量的問題。

 

3—存儲過程(中)

目前,EF對存儲過程的支持並不完善。存在如下問題:

l EF不支持存儲過程返回多表聯合查詢的結果集。

l EF僅支持返回返回某個表的所有字段,以便轉換成對應的實體。沒法支持返回部分字段的狀況。

l 雖然能夠正常導入返回標量值的存儲過程,可是卻沒有爲咱們自動生成相應的實體.cs代碼,咱們仍是沒法在代碼中直接調用或使用標量存儲過程

l EF不能直接支持存儲過程當中Output類型的參數。

l 其餘一些問題。

本節,咱們將學習如何手動添加/修改存儲過程,如何使EF可以支持Output類型的參數。

l 添加/修改存儲過程

有時候,某個SQL語句比較複雜,可是數據庫中又沒有定義相應的存儲過程。這個時候,咱們又想使上層代碼比較簡單、方便的方式來完成此項任務。那麼,此時,咱們即可以手工在實體模型(.edmx文件)中添加本身須要的存儲過程了。這樣既方便上層調用又方便後期的修改。

以手動修改實體模型edmx文件,添加名爲CustomerByCommandText的存儲過程爲例。具體步驟以下:

修改實體模型文件,找到ssdl部分,添加以下代碼:



select c.* from Customers c,Orders o where c.CustomerID=o.CustomerID

而後,再找到csdl部分,添加以下代碼:

 

接着,找到msl部分,添加以下代碼:

 

最後,在實體模型的.cs文件裏面,添加一個執行此存儲過程的方法,代碼以下:

public global ::System.Data.Objects.ObjectResult GetCustomerByCommandText()
{
return base.ExecuteFunction("CustomerByCommandText");
}

至此,修改完畢。

如今,咱們就能夠在代碼使用剛纔手工定義的存儲過程了。以下代碼所示:

[Test]
public void GetCustomerByCmdText()
{
using (var db = new NorthwindEntities())
{
var csts = db.GetCustomerByCommandText().Take(10).Skip(0);
foreach (var c in csts)
Console.WriteLine(c.CustomerID);
}
}

其實,關鍵的地方就是CommandText這個部分的內容,它裏面就是要執行的SQL語句。另外,咱們能夠在修改實體模型emdx文件的同時,咱們能夠看到全部的實體類查詢的SQL語句命令均可以在edmx文件裏找到,咱們均可以進行相應的修改。

 

l Output類型參數

在實際應用當中,不少時候,咱們須要使用output類型的存儲過程參數,以便返回咱們須要的值。可是,目前,EF不能直接支持output類型的存儲過程參數。爲此,咱們須要對實體模型進行修改,以便使其支持output類型的輸出參數。具體過程以下:

在數據庫中創建一個爲名的GetNameByCustomerId存儲過程,代碼以下:

CREATE PROCEDURE GetNameByCustomerId
@CustomerId varchar(5),
@ContactName varchar(30) output
AS
BEGIN
SET NOCOUNT ON;
SELECT @ContactName=ContactName
FROM Customers
WHERE CustomerID=@CustomerId;
END

而後,開始修改實體模型edmx文件。

先找到ssdl定義的部分,添加以下代碼:




接着,在找到csdl定義的部分,添加以下代碼:




最後,找到msl定義的部分,添加以下代碼:

 

至此,實體模型emdx文件修改完畢。

接下來,咱們須要在實體模型的.cs文件中,增長相應的調用方法。代碼以下:

public partial class NorthwindEntities1
{

//執行GetNameByCustomerId的方法
public void GetNameByCustomerId(string CustomerId, out string ContactName)
{
ContactName = string.Empty;
var Pars = new System.Data.EntityClient.EntityParameter[]
{
new System.Data.EntityClient.EntityParameter{ ParameterName="CustomerId", DbType=System.Data.DbType.String,Value=CustomerId},
new System.Data.EntityClient.EntityParameter{ParameterName="ContactName", DbType=System.Data.DbType.String, Direction=System.Data.ParameterDirection.Output}
};
this.ExecuteNonQuery("GetNameByCustomerId", Pars);
ContactName = Pars[1].Value.ToString();

}

//輔助方法,執行SQL命令
private void ExecuteNonQuery(string functionName, System.Data.EntityClient.EntityParameter[] parameters)
{
System.Data.EntityClient.EntityCommand cmd = ((System.Data.EntityClient.EntityConnection)this.Connection).CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddRange(parameters);
cmd.CommandText = this.DefaultContainerName + "." + functionName;
try
{
if (cmd.Connection.State != System.Data.ConnectionState.Open)
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
catch (System.Exception)
{
throw;
}
finally
{
cmd.Connection.Close();
}
}
}

如今,全部的修改工做都作完了。接下來,咱們就能夠在代碼中直接調用此存儲過程了。示例代碼以下:

[Test]
public void OutputTest()
{
using (var db = new NorthwindModel .NorthwindEntities1())
{
string contactname = string.Empty;
db.GetNameByCustomerId("ALFKI", out contactname);
Assert.IsTrue(!string.IsNullOrEmpty(contactname));
Console.WriteLine(contactname);
}
}

至此,咱們即可以使用Output類型的輸出參數了。

 

4—存儲過程(下)

在EF中,各個實體的插入、更新和刪除也都經過使用存儲過程來完成,以便提升點性能。這個相似於數據集。其步驟是:先定義存儲過程,而後在VS的可視化設計器,設置存儲過程映射便可。

下面,覺得Supplier實體映射存儲過程爲例。

分別創建插入、更新和刪除存儲過程。

InsertSuppliers存儲過程定義以下:

CREATE PROCEDURE [dbo].[InsertSuppliers]

-- Add the parameters for the stored procedure here

@CompanyName nvarchar(40),

@ContactName nvarchar(30),

@ContactTitle nvarchar(30),

@Address nvarchar(60),

@City nvarchar(15),

@Region nvarchar(15),

@PostalCode nvarchar(10),

@Country nvarchar(15),

@Phone nvarchar(24),

@Fax nvarchar(24),

@HomePage ntext

AS

BEGIN

-- SET NOCOUNT ON added to prevent extra result sets from

-- interfering with SELECT statements.

SET NOCOUNT ON;

INSERT INTO Suppliers(CompanyName,ContactName,ContactTitle,Address,City,Region,PostalCode,Country,Phone,Fax,HomePage)

VALUES(@CompanyName,@ContactName,@ContactTitle,@Address,@City,@Region,@PostalCode,@Country,@Phone,@Fax,@HomePage);

SELECT SCOPE_IDENTITY() AS SupplierID;

END

 

DeleteSuppliers存儲過程定義以下:

CREATE PROCEDURE [dbo].[DeleteSuppliers]

-- Add the parameters for the stored procedure here

@SupplierID int

AS

BEGIN

-- SET NOCOUNT ON added to prevent extra result sets from

-- interfering with SELECT statements.

SET NOCOUNT ON;

DELETE Suppliers WHERE SupplierID=@SupplierID

END

UpdateSuppliers存儲過程定義以下:

CREATE PROCEDURE [dbo].[UpdateSuppliers]

-- Add the parameters for the stored procedure here

@SupplierID int,

@CompanyName nvarchar(40),

@ContactName nvarchar(30),

@ContactTitle nvarchar(30),

@Address nvarchar(60),

@City nvarchar(15),

@Region nvarchar(15),

@PostalCode nvarchar(10),

@Country nvarchar(15),

@Phone nvarchar(24),

@Fax nvarchar(24),

@HomePage ntext

AS

BEGIN

-- SET NOCOUNT ON added to prevent extra result sets from

-- interfering with SELECT statements.

SET NOCOUNT ON;

UPDATE Suppliers SET CompanyName=@CompanyName,ContactName=@ContactName,ContactTitle=@ContactTitle,Address=@Address,City=@City,Region=@Region,PostalCode=@PostalCode,Country=@Country,Phone=@Phone,Fax=@Fax,HomePage=@HomePage

WHERE SupplierID=@SupplierID

END

而後,在VS可視化設計器中,打開實體模式edmx文件,而後在Suppliers實體上鼠標右鍵à「存儲過程映射」,而後在在分別設置存儲過程便可。以下圖所示:

 

至此,存儲過程映射完畢。咱們下面來具體的使用,代碼以下:

使用存儲過程Insert:

[Test]

public void SPInsert()

{

using (var db = new NorthwindEntities1())

{

var supplier = new Suppliers();

supplier.CompanyName = "cnblogs";

supplier.ContactName = "xray2005";

supplier.ContactTitle = "net";

supplier.City = "成都";

supplier.Region = "四川";

supplier.Country = "中國";

supplier.PostalCode = "600041";

supplier.Phone = "028-8001";

supplier.Fax = "028-8002";

supplier.HomePage = "http://xray2005.cnblogs.com";

db.AddToSuppliers(supplier);

db.SaveChanges();



}

}

使用存儲過程Update:

[Test]

public void SPUpdate()

{

using (var db = new NorthwindEntities1())

{

var supplier = db.Suppliers.FirstOrDefault(s => s.SupplierID == 30);

Assert.IsNotNull(supplier);

supplier.CompanyName = "CNBLOGS";

supplier.ContactName = "xray2005";

supplier.ContactTitle = "♂風風車.net";

supplier.City = "成都";

supplier.Region = "四川";

supplier.Country = "China";

supplier.PostalCode = "600040";

supplier.Phone = "028-1008611";

supplier.Fax = "028-10086";

supplier.HomePage = "http://www.cnblogs.com/xray2005";

db.SaveChanges();



}

}

使用存儲過程Delete:

[Test]

public void SPDelete()

{

using (var db = new NorthwindEntities1())

{

var supplier = db.Suppliers.FirstOrDefault(s => s.SupplierID == 31);

Assert.IsNotNull(supplier);

db.DeleteObject(supplier);

db.SaveChanges();

var supplier1 = db.Suppliers.FirstOrDefault(s => s.SupplierID == 31);

Assert.IsNull(supplier1);

}

}

至此,實體存儲過程映射介紹完畢。本節,內容比較簡單。

 

5—使EF支持Oracle9i

從Code MSDN上下載下來的EFOracleProvider不支持Oracle9i.可是,目前我所使用的仍是Oracle9i。爲此,對EFOracleProvider修改瞭如下,以便使其支持Oracle9i.

下面說說具體修改地方.(紅色部分爲添加或修改的代碼部分)

一,修改EFOracleProvider

1,修改EFOracleProviderManifest.cs類文件,

internal const string TokenOracle9i = "9i";//add by xray2005

internal const string TokenOracle10g = "10g";

internal const string TokenOracle11g = "11g";

如下兩個地方,不修改也是能夠的.但考慮目前我主要是使用9i,因此也就修改爲9i了.

private EFOracleVersion _version = EFOracleVersion.Oracle9i; //EFOracleVersion.Oracle11g;

private string _token = TokenOracle9i; //TokenOracle10g;

2,修改EFOracleVersion.cs類文件,以下代碼所示:

namespace EFOracleProvider

{

using System;

///



/// This enum describes the current storage version

///


internal enum EFOracleVersion

{

Oracle9i = 9, //add by xray2005

///

/// Oracle10g

///

Oracle10g = 10,



///

/// Oracle 11g

///

Oracle11g = 11,

// higher versions go here

}

///

/// This class is a simple utility class that determines the version from the 

/// connection

///

internal static class EFOracleVersionUtils

{

///

/// Get the version from the connection.

///

/// current connection

/// version for the current connection

internal static EFOracleVersion GetStorageVersion(EFOracleConnection connection)

{

string serverVersion = connection.ServerVersion;

if (serverVersion.StartsWith("9.")) 

{

return EFOracleVersion.Oracle9i; //add by xray2005

}

else if (serverVersion.StartsWith("10."))

{

return EFOracleVersion.Oracle10g;

}

else if (serverVersion.StartsWith("11."))

{

return EFOracleVersion.Oracle11g;

}

throw new ArgumentException("Could not determine storage version; " +

"a valid storage connection or a version hint is required.");

}

internal static string GetVersionHint(EFOracleVersion version)

{

switch (version)

{

case EFOracleVersion.Oracle9i:

return EFOracleProviderManifest.TokenOracle9i; //add by xray2005

case EFOracleVersion.Oracle10g:

return EFOracleProviderManifest.TokenOracle10g;

case EFOracleVersion.Oracle11g:

return EFOracleProviderManifest.TokenOracle11g;

default:

throw new ArgumentException("Could not determine storage version; " +

"a valid storage connection or a version hint is required.");

}

}

internal static EFOracleVersion GetStorageVersion(string versionHint)

{

if (!string.IsNullOrEmpty(versionHint))

{

switch (versionHint)

{

case EFOracleProviderManifest.TokenOracle9i:

return EFOracleVersion.Oracle9i; //add by xray2005

case EFOracleProviderManifest.TokenOracle10g:

return EFOracleVersion.Oracle10g;

case EFOracleProviderManifest.TokenOracle11g:

return EFOracleVersion.Oracle11g;

}

}

throw new ArgumentException("Could not determine storage version; " +

"a valid storage connection or a version hint is required.");

}



internal static bool IsVersionX(EFOracleVersion storageVersion)

{

return storageVersion == EFOracleVersion.Oracle9i || storageVersion == EFOracleVersion.Oracle10g ||

storageVersion == EFOracleVersion.Oracle11g; //add by xray2005

}

}

}

 

 

二,使用EFOracleProvider

修改完畢後,編譯一下.若是是本身下載的源代碼編譯的,那麼編譯後的EFOracleProvider自動已經在GAC註冊了.若是是手動註冊EFOracleProvider到GAC,那麼命令以下:

gacutil –I 「EFOracleProvider.dll 」

其中gacutil.exe位於:系統盤符號:\Program Files\Microsoft SDKs\Windows\v6.0A\bin下面。

接下來,咱們須要作的就是,把這個EFOracleProvider添加到Machine.config中.

第一步,找到Machine.config文件.該文件的位置在:

系統盤符號:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG下面.

第二步,用打開Machine.config文件,在DbProviderFactories配置節點,增長EFOracleProvider的配置,以下所示:















第三步,保存便可.

接下來,簡單的介紹一下,如何使用這個EFOralceProvider.

第1步:在命令行窗口,將目錄定位到提示符, 系統盤符:\WINDOWS\Microsoft.NET\Framework\v3.5.以下所示(是我電腦上的目錄):

548x23

 

第2步,輸入相應的生成參數.以下圖所示:

641x57

將「data source=test;user id=xray;password= 123」成你本身的對應的參數便可.

肯定以後,就能夠看到生成的結果了,同時會有寫信息出來,以下示:

642x326

至此,EdmGen就爲咱們生成須要的文件.生成的文件以下所示:

l TestEFModel .csdl

l TestEFModel .msl

l TestEFModel .ssdl

l TestEFModel .ObjectLayer.cs

l TestEFModel .Views.cs

 

而後,經過EdmGen2工具, 使用剛剛生成的TestEFModel .csdl , TestEFModel .msl , TestEFModel .ssdl三個文件來生成一個模型.

命令以下:

Edmgen2.exe /toedmx TestEFModel .csdl TestEFModel .msl TestEFModel .ssdl

肯定以後,該工具就會爲咱們生成一個TestEFModel .edmx文件了.

而後,把這個文件加入到咱們的項目中,同時修改項目的App.Config文件鏈接字符串,以下所示:








connectionString="provider=EFOracleProvider;

metadata=res://*/TestEFModel .csdl |res://*/TestEFModel .ssdl |res://*/TestEFModel .msl ;

Provider Connection String='data source=test;user id=xray;password=1111'"

providerName="System.Data.EntityClient" />



最後保存.

至此,修改EFOracleProvider並使用,介紹完畢。

最後提供幾個鏈接,以方便你們學習研究:

l Code.MSDN上的EFOracleProvider;

l 通過我修改後,支持Oracle9i的EFOracleProvider.dll

l EdmGen2.exe

相關文章
相關標籤/搜索