Entity Framework Code First在Oracle下的偽實現


為什么要說是偽實現,因為還做不到類似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文件中去配置監聽地址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM