繁体   English   中英

实体框架代码优先GenericTypeArguments

[英]Entity Framework Code First GenericTypeArguments

我有一个不幸的任务是创建一个同时使用MySQL和MSSQL数据库的MVC项目。 为此,我首先使用Entity Framework 6代码,并且在两个数据库上都可以使用它。

但是,问题在于MSSQL支持模式,而MYSQL不支持。 如果添加modelBuilder.Entity<Status>().ToTable("Status", schemaName: "Client"); 我在构建MySQL数据库时出错。

为了解决这个问题,我尝试将自定义属性添加到所有DbSet中,以便能够确定要使用的架构。 在MSSQL中,我将使用架构,而在MYSQL中,我将在表前添加架构名称。

例如:

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类型或动态更改模式和表名的替代方法。

更新:

我设法通过将类型强制转换为动态类型来获取类型。 但是随后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 });
                }


            }

您现在处于反思的境界。 尝试如下所示的方法:

        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 } );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM