為什么要說是偽實現,因為還做不到類似MsSql中那樣完全的功能。Oralce中的數據庫還是要我們自己手動去創建的。這里,我們舍掉了Model First中的EDMX文件,自己在代碼里面寫模型與映射關系,這又有點像是Code First模型了,所以我說它是一個偽實現。真正完全的Code First應該是要通過Oracle開發驅動來支持了。
通過EF來連接Oracle數據庫,前提是要下載ODP.NET驅動。Google一下就找得到了。
模型
public class Student { public Student() { this.Teachers = new HashSet<Teacher>(); } public Guid ID { get; set; } public string Name { get; set; } public int StudnetNumber { get; set; } public bool IsMale { get; set; } public virtual ICollection<Teacher> Teachers { get; set; } } public class Teacher { public Teacher() { this.Students = new HashSet<Student>(); } public Guid ID { get; set; } public string Name { get; set; } public virtual ICollection<Student> Students { get; set; } }
模型很簡單,這里寫了兩個示例模型,Student 與Teacher,並且它們之間是多對多的關系。
主鍵的配制
Oralce數據庫中主鍵有兩種方式:后台通過數據庫自己去生,比如:trigger+sequence結合的方式來產生自增長的主鍵;還有一種就是通過前台顯示的給ID賦值,如ID=1來插入到數據庫庫中。如果你想通過前台自己手動來插入的話,要配置主鍵的自增長為NONE。
HasKey(k => k.ID);
Property(p => p.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
數據類型的映射
ODP.NET能夠支持大多數數據類型的自動映射,比如int,datetime,string等。但對於一些特別數據類型,比如boolean,guid,Oracle數據庫中並沒有對應的bit類型或是GUID類型。我們要在映射的時候顯示指定。
//GUID類型的映射 Property(p => p.TypeCode).HasColumnName("TYPECODE").HasColumnType("GUID"); //boolean類型的映射 Property(p => p.IsSale).HasColumnName("ISSALE").HasColumnType("odp_internal_use_type");
關系的映射
ODP.NET能夠很好的支持一對多的映射,一對多的映射就像我們在配置MsSql數據庫中一樣。
多對多關系的映射:因為兩個多對多的表,會產生一個中間表,用來保存這兩張表的主鍵,這就要求EF能夠獲得這兩張表的主鍵。如果這兩張表的主鍵是在數據庫中通過Sequence來生成的,EF就無法獲取。所以,如果要配置表之間的多對多關系,表的主鍵必須是通過前台顯示插入的。
HasMany(t => t.Teachers).WithMany(s => s.Students).Map(m => { m.MapLeftKey("STUDENTID"); m.MapRightKey("TEACHERID"); m.ToTable("STUDENT_TEACHER", "GYOUNG"); });
總的映射如下:
public class StudentConfiguration : EntityTypeConfiguration<Student> { public StudentConfiguration() { HasKey(k => k.ID); Property(p => p.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None) //GUID類型的映射 .HasColumnType("GUID"); Property(p => p.Name).HasColumnName("NAME"); //bool類型的映射 Property(p => p.IsMale).HasColumnName("ISMALE").HasColumnType("odp_internal_use_type"); Property(p => p.StudentNumber).HasColumnName("STUDENTNUMBER"); HasMany(t => t.Teachers).WithMany(s => s.Students).Map(m => { //LeftKey 當前表的主鍵 m.MapLeftKey("STUDENTID"); //RightKey 另一張表的主鍵 m.MapRightKey("TEACHERID"); //必須指定數據庫架構名稱 m.ToTable("STUDENT_TEACHER", "GYOUNG"); }); //表名+數據庫架構名 ToTable("STUDENT", "GYOUNG"); } } public class TeacherConfiguration : EntityTypeConfiguration<Teacher> { public TeacherConfiguration() { HasKey(k => k.ID); Property(p => p.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None) .HasColumnType("GUID"); Property(p => p.Name).HasColumnName("NAME"); ToTable("TEACHER", "GYOUNG"); } }
DbContext
public class TestContext : DbContext { public DbSet<Student> Students { get; set; } public DbSet<Teacher> Teachers { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new TeacherConfiguration()).Add(new StudentConfiguration()); base.OnModelCreating(modelBuilder); } }
附創建表的SQL:
-- Creating table 'TEACHERS' CREATE TABLE "GYOUNG"."TEACHERS" ( "ID" RAW(16) NOT NULL, "NAME" NVARCHAR2(200) NULL ); -- Creating table 'STUDENTS' CREATE TABLE "GYOUNG"."STUDENTS" ( "ID" RAW(16) NOT NULL, "NAME" NVARCHAR2(200) NULL, "ISMALE" NUMBER(10,0) NULL, "STUDENTNUMBER" NUMBER(10,0) NULL ); -- Creating table 'STUDENT_TEACHER' CREATE TABLE "GYOUNG"."STUDENT_TEACHER" ( "STUDENTID" RAW(16) NOT NULL, "TEACHERID" RAW(16) NOT NULL );
忘記了配置,補貼一下:
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <connectionStrings> <add name="MfTest" providerName="Oracle.DataAccess.Client" connectionString="Data Source=Gyoung;user id=test;password=123456" /> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> </entityFramework> <oracle.dataaccess.client> <settings> <add name="bool" value="edmmapping number(1,0)" /> <add name="byte" value="edmmapping number(3,0)" /> <add name="int16" value="edmmapping number(4,0)" /> <add name="int32" value="edmmapping number(9,0)" /> <add name="int64" value="edmmapping number(18,0)" /> </settings> </oracle.dataaccess.client> </configuration>
MfTest就是連接字符串,和SQLSERVER差不多,並沒有什么關鍵的設計。數據庫名是Gyoung,你自己要在Oracle中tnsnames.ora文件中去配置監聽地址。