我有一个问题,它完全停留在该做什么。我是EF新手:(
我使用了Adriaan Booysen的code创建了一个动态模型。由于局限性,我不能使用WCFDataService
,而且我已经改变了一些代码以使其适用于我。当我第一次运行它时,它工作,我得到我的数据,但是当我再次执行该方法时,我得到的错误是实体类型不是模型的一部分。
我注意到的是,当我运行应用程序并创建第一个实体时,OnModelCreating被触发,并且模型被添加,但第二次没有发生,我认为这就是我得到错误的原因,但是我不知道该怎么办才能再次开火。
这是DynamicDbContext
的代码
public partial class DynamicDbContext : DbContext
{
public DynamicDbContext()
: base("name=DynamicDbContext")
{
Database.SetInitializer(new NullDatabaseInitializer<DynamicDbContext>());
}
public void AddTable(Type type, List<string> KeyFields)
{
_tables.Add(type.Name, type);
_keys = KeyFields;
}
private List<string> _keys;
private Dictionary<string, Type> _tables = new Dictionary<string, Type>();
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
var entityMethod = modelBuilder.GetType().GetMethod("Entity");
foreach (var table in _tables)
{
entityMethod.MakeGenericMethod(table.Value).Invoke(modelBuilder, new object[] { });
foreach (var pi in (table.Value).GetProperties())
{
if (_keys.Contains(pi.Name.ToUpper()))
modelBuilder.Entity(table.Value).HasKey(pi.PropertyType, pi.Name);
else
switch (pi.PropertyType.Name)
{
case "Int16":
case "Int32":
case "Int64":
case "Boolean":
modelBuilder.Entity(table.Value).PrimitiveProperty(pi.PropertyType, pi.Name);
break;
default:
modelBuilder.Entity(table.Value).DynamicProperty(pi.PropertyType, pi.Name);
break;
}
}
}
}
}
我有一个班级然后得到DbSet
public class Class1 : DynamicDbContext
{
public DbSet LoadTypes(string TableName, Dictionary<string, Type> Fields, List<string> KeyFields)
{
var dcf = new DynamicClassFactory("Query." + TableName);
var type = CreateType(dcf, TableName, Fields);
AddTable(type, KeyFields);
return Set(type);
}
private static Type CreateType(DynamicClassFactory dcf, string name, Dictionary<string, Type> Fields)
{
var type = dcf.CreateDynamicType<BaseDynamicEntity>(name, Fields);
return type;
}
}
DynamicClassFactory
创建了内存组件。如果您查看代码项目代码,您可以看到它的作用。我没有改变任何东西。
在我的申请中,我执行以下操作:
var c = new Class1();
var Types = new Dictionary<string, Type>();
/*Code to populate the Fields and Field Types into the Types variable*/
source.QueryableSource = c.LoadTypes(TableName, Types, new List<string>() { "NO" });
source是来自DevExpress的EntityServerModeSource
,允许我更有效地填充一个支点。如果有人能指出我正确的方向,我可以弄清楚,但目前我不知道该怎么办。
嘿,我认为这很可能是由于即使您处置上下文,您将遇到一些问题与EF缓存模型构建器的东西
public class DwContext : DbContext, IDbModelCacheKeyProvider
{
string IDbModelCacheKeyProvider.CacheKey => DwContextSettings.cacheKey;
...
}
我通过使用编译模型来实现它。因为我没有创建数据库或在模型中进行任何更新,插入或删除,只是使用它来从一个或多个表中检索数据,我将代码从OnModelCreating移动到我的DbContext类中的静态方法,并调用它来自构造函数,它在打开查询时编译模型。这是代码
public DynamicDbContext(string connString, Type type, List<string> KeyFields)
: base(GetConnection(connString), GenerateDbCompiledModel(connString, type, KeyFields), true)
{
Database.SetInitializer(new NullDatabaseInitializer<DynamicDbContext>());
}
private static DbConnection GetConnection(string connectionString)
{
var factory = DbProviderFactories.GetFactory("Oracle.ManagedDataAccess.Client");
var conn = factory.CreateConnection();
conn.ConnectionString = connectionString;
return conn;
}
public static DbCompiledModel GenerateDbCompiledModel(string connectionString, Type entityType, List<string> _keys)
{
string tableName = entityType.Name;
string schema = entityType.FullName.Replace("Dynamic.Objects.", "").Replace("." + tableName, "");
_keys = _keys.Select(x =>
{
x = x.ToUpper();
return x;
}).ToList();
tableName = entityType.Name;
DbModelBuilder dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest);
var entityMethod = dbModelBuilder.GetType().GetMethod("Entity");
dbModelBuilder.HasDefaultSchema(schema);
entityMethod.MakeGenericMethod(entityType).Invoke(dbModelBuilder, new object[] { });
foreach (var pi in (entityType).GetProperties())
{
if (_keys.Contains(pi.Name.ToUpper()))
dbModelBuilder.Entity(entityType).HasKey(pi.PropertyType, pi.Name);
else
switch (pi.PropertyType.Name)
{
case "Int16":
case "Int32":
case "Int64":
case "Boolean":
dbModelBuilder.Entity(entityType).PrimitiveProperty(pi.PropertyType, pi.Name);
break;
default:
dbModelBuilder.Entity(entityType).DynamicProperty(pi.PropertyType, pi.Name);
break;
}
}
var factory = DbProviderFactories.GetFactory("Oracle.ManagedDataAccess.Client"); // Oracle.ManagedDataAccess.Client");
var conn = factory.CreateConnection();
conn.ConnectionString = connectionString;
return dbModelBuilder.Build(conn).Compile();
}
我有GetConnection的原因是因为应用程序也使用Devart,并且由于某种原因,new OracleConnection
使用了其中一个,这给了我另一个错误消息。
我的实体包含了Schema和Table Name作为全名的一部分,这就是为什么我可以从qazxsw poi中提取模式的原因
我希望这有助于那些想要动态创建实体模型以供显示的人。
当您的连接字符串不正确时,问题通常会发生。检查提供商名称和可能的EF内容