一個腳本服務的項目,之前是先設計的數據庫表,采用EF的dbfirst做的映射。項目完成后,出現遷移瓶頸。
1、dbfirst項目,如果數據庫表結構做了調整,需要重新映射
2、當出現表結構一致,但數據庫用戶及密碼發生變化時,原dbfirst映射無法適應新數據庫,需要重新建立dbfirst映射。不易於遷移
考慮這個腳本服務的目地是:
1、采用EF6 codefirst(廢棄dbfirst)
2、目前腳本服務器以承載庫是oracle,解決了oracle版本不一致造成兼容性問題
3、可以直接將發布版的腳本服務器隨意遷移至其他服務器或新建為多個腳本服務
4、oracle數據庫地址發生變化時,直接在配置文件中修改數據庫鏈接地址和Database.Schema
我在將該項目從dbfirst遷移到codefirst的步驟如下:
1、升級項目。由於我原來項目是FM4.0、EF5.0 用vs2012開發的,現在將項目升級為FM4.5、EF6,故新建了一個類庫,創建了一個ADO.NET實體數據模型。用於自動引用EF6相關dll文件。之后刪除 XX.edmx
2、copy映射實體類。建立新文件夾Entity,拷貝在dbfirst中生成實體映射類至該目錄下
3、加工dbfirst而來的實體類。為主鍵加入[Key]特性,為外鍵加入[ForeignKey("外鍵字段的屬性名")]。如下:

namespace Easyman.Service { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; public partial class EM_SCRIPT_REF_NODE { [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] public long ID { get; set; } public Nullable<long> SCRIPT_ID { get; set; } public Nullable<long> PARENT_NODE_ID { get; set; } public Nullable<long> CURR_NODE_ID { get; set; } public string REMARK { get; set; } [ForeignKey("SCRIPT_ID")] public virtual EM_SCRIPT EM_SCRIPT { get; set; } } }
4、新建DBEntities類,繼承DbContext。代碼參照如下:

namespace Easyman.Service { using System; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Configuration; using System.Data.Common; public partial class DBEntities : DbContext { public DBEntities() : base("name=DBEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { //var schema = ConfigurationManager.AppSettings["Database.Schema"]; var schema = ConfigurationSettings.AppSettings["Database.Schema"]; modelBuilder.HasDefaultSchema(schema); base.OnModelCreating(modelBuilder); } public DbSet<EM_ANALYSIS> EM_ANALYSIS { get; set; } public DbSet<EM_CONNECT_LINE> EM_CONNECT_LINE { get; set; } } }
5、接下來是配置文件:配置數據鏈接、Schema用戶名,同時解決oracle版本兼容和驅動問題

<?xml version="1.0" encoding="utf-8"?> <!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=301880 --> <configuration> <configSections> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> </configSections> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> <providers> <!--<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />--> <provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" /> </providers> </entityFramework> <appSettings> <!--以下是腳本服務名稱配置信息 --> <!--腳本服務器描述文字 --> <add key="Description" value="開發三部的腳本服務器" /> <!--腳本服務顯示的名稱 --> <add key="DisplayName" value="Easyman3Script" /> <!--腳本服務的服務名 --> <add key="ServiceName" value="Easyman3Script" /> <!--以下是數據庫用戶名Schema --> <add key="Database.Schema" value="C##ABPBASE" /> </appSettings> <connectionStrings> <add name="DBEntities" connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=xx.xx.xx.xx)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)));User ID=C##ABPBASE;Password=C##ABPBASE;Persist Security Info=True" providerName="Oracle.ManagedDataAccess.Client" /> </connectionStrings> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-1.2.13.0" newVersion="1.2.13.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Common.Logging.Core" publicKeyToken="af08829b84f0328e" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> <system.data> <DbProviderFactories> <remove invariant="Oracle.ManagedDataAccess.Client" /> <add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" /> </DbProviderFactories> </system.data> <oracle.manageddataaccess.client> <version number="*"> <dataSources> <dataSource alias="SampleDataSource" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) " /> </dataSources> </version> </oracle.manageddataaccess.client> </configuration>
以上步驟完成后,項目能夠正常生成。運行過程出現的問題:
1、數據庫版本問題
其他信息: 無法為具有固定名稱“Oracle.ManagedDataAccess.Client”的 ADO.NET 提供程序加載在應用程序配置文件中注冊的實體框架提供程序類型“Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342”。請確保使用限定程序集的名稱且該程序集對運行的應用程序可用。有關詳細信息,請參閱 http://go.microsoft.com/fwlink/?LinkId=260882。
解決方式:引用oracle官方新出的dll文件Oracle.ManagedDataAccess.dll 和 Oracle.ManagedDataAccess.EntityFramework.dll
下載地址:oracle.dll.zip
參考鏈接:Entity Framework6 with Oracle(可實現code first)
2、能夠通過EF查詢數據,但是向數據庫寫入數據時,明明給主鍵ID賦值了,但是總是提示傳入的主鍵ID為空值。錯誤提示如下:
ORA-01400: 無法將 NULL 插入 ("C##ABPBASE"."EM_SCRIPT_CASE_LOG"."ID") ORA-06512: 在 line 4
參考網站:Entity Framework Code First 遭遇主鍵自動生成問題
原因:由於EF的codefirst默認設置表的主鍵ID為identity,不會將賦給主鍵ID的值傳入數據庫,而是由數據庫自增去賦值。
這種情況有兩種應對方式:
"C##ABPBASE"."EM_SCRIPT_CASE_SEQ".nextval

2)有選擇性的取消實體類的identity,表的主鍵值由用戶自己去賦值。配置如下:
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
