【问题标题】:Is there a way to create a table with EF6 using a DbModelBuilder directly?有没有办法直接使用 DbModelBuilder 创建带有 EF6 的表?
【发布时间】:2021-01-24 18:08:27
【问题描述】:

我正在寻找一种直接在我的数据库中为临时实体创建表的方法。由于数据库可以通过连接字符串定义,因此创建语句的语法在 postgres 和 Oracle 之间可能会有所不同 - 因此我不能将其写为纯文本命令。

有人知道如何从 EF6 中的 Entity / DbModelBuilder / DbModel / DbCompiledModel 实现这一目标吗?不得不提一下,我不能使用 EF Core。

这是我目前的设置:

public class TMPEntity
{
  public TMPEntity();

  public string EntityId{ get; set; }
}

var modelBuilder = new DbModelBuilder();

// set default schema
modelBuilder.HasDefaultSchema("SCHEMA");

// Create Table in this schema
modelBuilder.Entity<TMPEntity>().ToTable(tableName: "TMPEntityTable", schemaName: "SCHEMA");

modelBuilder.Entity<TMPEntity>().HasKey(
h => new
{
  h.EntityId
});

var ctx = modelBuilder
.Build(context.Database.Connection)
.Compile();

提前非常感谢!

【问题讨论】:

    标签: c# postgresql oracle entity-framework-6


    【解决方案1】:

    这就是我最终的结果。我猜这不是最好的解决方案,但至少是一个可行的解决方案,直到进一步的建议:-)

    由于我没有管理它以从 EdmModel 类或 DBModel 生成有效的 SQL,我创建了一个 DbMigration 类,它现在创建表。不像 ModelBuilder 方法那么聪明,但正如我所提到的 - 工作:

    internal class CreateSingleTableMigration: DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "\"SCHEMA\".\"TMPEntityTable\"",
                    c => new
                    {
                        // Single column
                        EntityId= c.String(nullable: false, maxLength: 150)
                        // Further columns go in here ...
                    })
                    .PrimaryKey(t => new { t.EntityId /*Combined PK goes here*/ });
            }
        }
    

    现在的问题是,如何使用选定的 IDbProvider 生成并执行有效的 SQL。由于我想重用现有的 DbContext,所有必需的信息都可以在这个类中获得。

    // If database exists
    if (context.Database.Exists())
    {
        // Get the corresponding DbProviderServices the Provider of the current Connection has to offer
        var serv = DbProviderServices.GetProviderServices(context.Database.Connection);
    
        // Get the provider manifest token
        var tkn = serv.GetProviderManifestToken(context.Database.Connection);
    
        // Get the PropertyInfo of the internal "Operations" property
        var prop = typeof(InitializeHistorizationMigration)
                     .GetProperty("Operations", BindingFlags.NonPublic | BindingFlags.Instance);
    
        // If Property "operations" was found
        if (prop != null)
        {
            // get SQL Generator for the current provider
            var generator = new Configuration().GetSqlGenerator(FWLPDataContext.Provider);
    
            // Create instance of the CreateTable-Migration
            var tmpMig= new CreateSingleTableMigration();
            // Apply it, so property "Operation" is filled
            tmpMig.Up();
    
            // Get the operations as a List of single MigrationOperation
            var operations = (prop.GetValue(tmpMig) as IEnumerable<MigrationOperation>).ToList();
    
            // Generate SQL and run it against the database using the DbContext Connection
            foreach (var item in generator.Generate(operations, tkn))
            {
                context.Database.ExecuteSqlCommand(item.Sql);
            }
        }
    }
    

    使用 postgres 执行 SQL 脚本产生错误:SqlState: 3F000 MessageText:没有选择要在其中创建的架构

    这就是我在 CreateSingleTableMigration 类中添加架构的原因,在连接字符串中设置搜索路径没有帮助。

    如果您对如何优化有更好的方法或想法,请告诉我!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 2022-11-28
      • 1970-01-01
      • 2018-11-10
      • 2019-11-06
      • 2020-07-02
      • 2010-12-04
      相关资源
      最近更新 更多