2014-04-10 190 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”)'解决了它。谢谢! –

相关问题