我有一个不幸的任务来创建一个同时使用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 });
}
}
那岂不是更容易申请表/架构名称中使用'而不是FluentAPI与反思'TableSchema'属性搞乱OnModelCreating'本身? – haim770
虽然起初这是更多的工作,但我认为在将来的开发中将所有表格设置放在一个位置会有好处,因此我不需要在代码顶部添加表格,然后添加对其的引用在'OnModelCreating'方法的底部 –