我有一個不幸的任務來創建一個同時使用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'方法的底部 –