2014-04-10 253 views
1

我有一個不幸的任務來創建一個同時使用MySQL和MSSQL數據庫的MVC項目。爲此,我首先使用Entity Framework 6代碼,並在兩個數據庫上工作。實體框架代碼第一個GenericTypeArguments

但問題是,MSSQL支持架構和MYSQL不支持。如果我添加了modelBuilder.Entity<Status>().ToTable("Status", schemaName: "Client");,我會在構建MySQL數據庫時出現錯誤。

爲了解決這個問題,我嘗試給我所有的DbSets添加一個自定義屬性,以便能夠確定我想要使用的模式。在MSSQL中,我將使用該模式,並且在MYSQL中,我將在表中添加模式名稱。

EG:

MSSQL: 
Client.Status 
Employee.Status 

MYSQL: 
Client_Status 
Employee_Status 

現在確定我想要使用反射的類型和模式。不幸的是,我不能在OnModelCreating方法中使用GenericTypeArguments。它說'System.Type' does not contain a definition for 'GenericTypeArguments' and ...

但是,如果我將反射代碼複製到我的MVC控制器(單獨項目)中的操作,它確實有效。

[TableSchema("Status", "Client")] 
    public DbSet<Tables.Status> Status { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     //launch debugger to see inspector 
     if (System.Diagnostics.Debugger.IsAttached == false) 
      System.Diagnostics.Debugger.Launch(); 

     //use schema or not 
     var useSchema = ConfigurationManager.AppSettings["UseSchema"] == "true"; 

     //get all properties 
     PropertyInfo[] properties = typeof(DataContext).GetProperties(BindingFlags.Public | BindingFlags.Instance); 

     foreach (PropertyInfo p in properties) 
     { 
      // Only work with dbsets 
      if (p.PropertyType.Name != "DbSet`1") { continue; } 

      //get tableschema attribute 
      var attribute = p.GetCustomAttributes(typeof(TableSchema), false).First(); 


      //the line below reports the error on building 
      var type = p.PropertyType.GenericTypeArguments.First().Name; 


      //the goal is to use something like 
      modelBuilder.Entity<type>().ToTable(attribute.Table, attribute.Schema); 

     } 
    } 

如果我取消與var type =線,並啓用調試,我也能看到GenericTypeArguments的檢查。

那麼我該如何使用GenericTypeArguments或類似的東西動態地獲取Tables.Status類型或動態地改變模式和表名的替代方法。

UPDATE:

我設法通過它強制轉換爲動態率先拿到類型。但隨後由Moho引入的第二部分代碼失敗

  var type = ((dynamic)p).PropertyType.GenericTypeArguments[0]; 

      if (type != null) 
      { 
       var t = modelBuilder.GetType(); 
       var m = t.GetMethod("Entity", BindingFlags.Public); 

       //System.NullReferenceException 
       var mgm = m.MakeGenericMethod((Type)type); 


       var entityTypeConfig = mgm.Invoke(modelBuilder, new object[] { }); 

       if (!useSchema) 
       { 
        entityTypeConfig.GetType() 
         .GetMethods() 
         .Single(mi => mi.Name == "ToTable" && mi.GetParameters().Count()==1) 
         .Invoke(entityTypeConfig, new object[] { attribute.Schema + "_" + attribute.Table }); 
       } 
       else 
       { 
        entityTypeConfig.GetType() 
         .GetMethods() 
         .Single(mi => mi.Name == "ToTable" && mi.GetParameters().Count() == 2) 
         .Invoke(entityTypeConfig, new object[] { attribute.Table, attribute.Schema }); 
       } 


      } 
+0

那豈不是更容易申請表/架構名稱中使用'而不是FluentAPI與反思'TableSchema'屬性搞亂OnModelCreating'本身? – haim770

+0

雖然起初這是更多的工作,但我認爲在將來的開發中將所有表格設置放在一個位置會有好處,因此我不需要在代碼頂部添加表格,然後添加對其的引用在'OnModelCreating'方法的底部 –

回答

1

您現在處於反思的境界。你可以試試下面的:

 var entityTypeConfig = modelBuilder.GetType() 
      .GetMethod("Entity") 
      .MakeGenericMethod(type) 
      .Invoke(modelBuilder, new object[] { }); 

     entityTypeConfig.GetType() 
      .GetMethods() 
      .Single(mi => mi.Name == "ToTable" && mi.GetParameters().Count == 2) 
      .Invoke(entityTypeConfig, new object[] { attribute.Table, attribute.Schema }); 
+0

謝謝。但問題是首先得到'type',因爲我不能使用'p.PropertyType.GenericTypeArguments'。經過一番搗鼓之後,我設法通過將它轉換爲動態來獲得類型,然後我可以使用'GenericTypeArguments'並且檢查器顯示正確的類型。但是當我在你的代碼中使用它時,我在'.MakeGenericMethod(type)' –

+0

上得到一個nullreference異常。所以問題不在於Type,而是在GetMethod(「Entity」,BindingFlags.Public)部分。顯然它不是一個公共方法,但是'GetMethod(「Entity」)'解決了它。謝謝! –

相關問題