无畏的承诺 發表於 2025-7-27 12:35:00

【EF Core】为 DatabaseFacade 扩展“创建”与“删除”数据表功能

<p>对于玩 EF 的大伙伴来说,对 DatabaseFacade 类的 EnsureCreated 和 EnsureDeleted 方法应该很熟悉。这对方法可在运行阶段创建或删除数据库。创建数据库时,会连同数据表一起创建;至于说删除数据库时嘛……库都没了,哪还有表呢。</p>
<p>不过,有些时候,不,不是有些时候,很多时候我们其实只想删除数据表。比如要初始化应用程序;或者数据库已存在的情况下,咱们只考虑判断数据表是否存在,不存在的话就创建表。</p>
<p>最简单的方法是直接发送 SQL 语句——如 DROP TABLE、DROP DATABASE 等。这个不在本文的讨论范围内。老周这次讨论的是运用 EF Core 自身的功能去实现。</p>
<p>咱们来热热身——先学点理论知识,有了这些知识,后面实战起来会容易很多。老掉牙的话:EF Core 也是基于服务容器。即支持依赖注入,这个东西好用着呢,也方便定制和扩展。微软在 .NET 上基本贯彻这个路线了。</p>
<p>咱们都知道,为了方便我们用面向对象的方式操作数据库,EF Core 内部实现了将相关操作以及 LINQ 转译为 SQL 的功能。尽管不能够完全覆盖 SQL 所有功能,但常用的一个不落。</p>
<p>下面介绍几个重量级角色:</p>
<h4>NO.1:IMigrationsSqlGenerator 接口。</h4>
<p>这个接口的功能很关键,看名字就知道,用来生成 SQL 语句的。这个接口只有一个&nbsp;Generate 方法,它的签名比较长:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> IReadOnlyList&lt;MigrationCommand&gt; Generate(IReadOnlyList&lt;MigrationOperation&gt; operations, IModel? model = <span style="color: rgba(0, 0, 255, 1)">default</span>, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default);</pre>
</div>
<p>第三个参数一般保留默认,第一个参数是一系列&nbsp;MigrationOperation 对象;第二个参数是模型对象,这个可以从 DbContext.Model 属性返回。<span class="hljs-title">MigrationOperation 是一个抽象类,表示一个数据库迁移操作(对的,dotnet ef migration 命令调用的正是迁移 API 来生成 SQL,再将其发送到数据库执行)。它的每一个派生类都代表一种操作。比如,DropColumnOperation 表示从数据表中删除一列,AddUniqueConstraintOperation 用于向数据表添加唯一约束。</span></p>
<p><span class="hljs-title">注意,这些 Operation 类型其实是“参数封装”器,各个属性用于收集此操作所需要的信息,各个数据库提供者都应该实现具体的操作。比如,在 SQL Server 提供者中,用于创建数据库的&nbsp;SqlServerCreateDatabaseOperation 类,Name 属性用于设置数据库的名字;FileName 属性设置数据库文件的路径,比如连接字符串中使用了 AttachDbFile 字段。</span></p>
<p><span class="hljs-title">现在说回&nbsp;IMigrationsSqlGenerator 接口,它有个基础实现类——&nbsp;MigrationsSqlGenerator。数据库提供者通常不必直接实现接口,而是从该类派生。例如官方默认实现的&nbsp;SqliteMigrationsSqlGenerator 类和&nbsp;SqlServerMigrationsSqlGenerator 类。Generate 方法返回一个&nbsp;MigrationCommand 列表,这个列表传递给&nbsp;IMigrationCommandExecutor 接口的&nbsp;ExecuteNonQuery 或&nbsp;ExecuteNonQueryAsync 方法就会执行 SQL 命令了。</span></p>
<h4><span class="hljs-title">NO.2:IMigrationCommandExecutor 接口</span></h4>
<p><span class="hljs-title">这个流程很明确,XXXSqlGenerator 负责生成 SQL,XXXCommandExecutor 负责执行命令。这个逻辑相信大伙伴们都能理解。这还不够,咱们还不知道怎么连接数据库呢,执行 SQL 前肯定得连接数据库的哟。于是,有请第三位。</span></p>
<h4><span class="hljs-title">NO.3:IRelationalConnection 接口</span></h4>
<p><span class="hljs-title">这个也不必过多介绍,就是用来连接数据库的。默认的基础类是&nbsp;RelationalConnection。不用意外,这货一定是抽象类的。毕竟,不同数据库的连接方式是不同的,所以,这个得让数据库提供者们自己去实现。比如面向 SQL Server 的&nbsp;SqlServerConnection 类,面向 SQLite 的&nbsp;SqliteRelationalConnection 类。</span></p>
<p><span class="hljs-title">当然了,IRelationalConnection 对象只是套个壳添加必要的逻辑,真正完成连接数据库任务的是 DbConnection 类(通过 DbConnection 属性引用)。如连接 Sqlite 数据库的&nbsp;SqliteConnection 类。</span></p>
<h4><span class="hljs-title">NO.4:IDatabaseCreator 接口</span></h4>
<p><span class="hljs-title">这个接口从名字上也能猜到,它是用来创建或删除数据库的。这个接口包含了咱们非常熟悉的 EnsureCreated 和 EnsureDeleted 方法。通常,咱们在用的时候不会从服务容器中获取此接口,而是它的派生接口——&nbsp;IRelationalDatabaseCreator。</span><strong><span style="color: rgba(255, 0, 0, 1)">重点来了,这</span></strong><span class="hljs-title">。<br></span></p>
<p><span class="hljs-title">再明显不过了,HasTables 返回 bool 值,表示数据表是否已存在;CreateTables 就是创建数据表。不过,DatabaseFacade 类没有这些方法,它只能创建、删除数据库。所以,咱们要做的,就是给它加扩展方法,把创建、删除表的方法封装出来。</span></p>
<p><span class="hljs-title">于是,咱们在实战部分,要分两个阶段。</span></p>
<p><span class="hljs-title">=====================================================================================</span></p>
<p><span class="hljs-title">理论课上完了,下面咱们动手实践。由于 IRelationalDatabaseCreator 已经实现了判断数据表存在性和创建数据表的功能,那咱们直接用它。先要定义一个静态类,比如,叫&nbsp;</span>MyDatabaseFacadeExtension。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyDatabaseFacadeExtension
{
   ……
}</span></pre>
</div>
<p>为了尽量少写重复代码,可以先搞个私有的扩展方法,用来获取&nbsp;IRelationalDatabaseCreator。</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> IRelationalDatabaseCreator GetDBCreator(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
   </span><span style="color: rgba(0, 0, 255, 1)">return</span> db.GetService&lt;IRelationalDatabaseCreator&gt;<span style="color: rgba(0, 0, 0, 1)">();
}</span></pre>
</div>
<p>这个很简单,DatabaseFacade 对象就有一个 GetService 方法,可直接从服务容器中取对象。</p>
<p>接着实现数据表的存在性判断—— HasTables。</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 判断表是否存在
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> HasTables(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
   IRelationalDatabaseCreator creator </span>=<span style="color: rgba(0, 0, 0, 1)"> db.GetDBCreator();
   </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> creator.HasTables();
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Task&lt;<span style="color: rgba(0, 0, 255, 1)">bool</span>&gt; HasTablesAsync(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
   IRelationalDatabaseCreator creator </span>=<span style="color: rgba(0, 0, 0, 1)"> db.GetDBCreator();
   </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> creator.HasTablesAsync();
}</span></pre>
</div>
<p>随后就是创建表的封装,也很简单。</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建表
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> CreateTables(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
   IRelationalDatabaseCreator creator </span>=<span style="color: rgba(0, 0, 0, 1)"> db.GetDBCreator();
   creator.CreateTables();
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task CreateTablesAsync(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
   IRelationalDatabaseCreator creator </span>=<span style="color: rgba(0, 0, 0, 1)"> db.GetDBCreator();
   </span><span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> creator.CreateTablesAsync();
}</span></pre>
</div>
<p>&nbsp;</p>
<p>上面的都好弄,最难的来了!IRelationalDatabaseCreator 只实现了创建表,可没有删除表啊。所以,只好自己动手了。</p>
<p>回想一下前文的理论热身,咱们是不是需要三个服务接口?</p>
<p><span style="color: rgba(0, 0, 128, 1)">1、IRelationalConnection:负责连接数据库;</span></p>
<p><span style="color: rgba(0, 0, 128, 1)">2、IMigrationsSqlGenerator:负责生成 SQL 命令;</span></p>
<p><span style="color: rgba(0, 0, 128, 1)">3、IMigrationCommandExecutor:负责执行命令。</span></p>
<p>由于在调用服务方法时咱们需要 IModel,而它一般可从 DbContext 对象的 Model 属性获取。所以咱们还要想办法从 DatabaseFacade 对象中获取当前 DbContext 对象的引用(其实是从 DbContext 派生的类实例)。仔细观察,可发现 DatabaseFacade 类显示实现了&nbsp;IDatabaseFacadeDependenciesAccessor 接口,而这个接口有个 Context 属性,正好能获取到 DbContext 实例。</p>
<p>好了,现在,所有难题都解决了,可以开干了。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 删除表
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> RemoveTables(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取服务</span>
    IRelationalConnection conn = db.GetService&lt;IRelationalConnection&gt;<span style="color: rgba(0, 0, 0, 1)">();
    IMigrationsSqlGenerator generator </span>= db.GetService&lt;IMigrationsSqlGenerator&gt;<span style="color: rgba(0, 0, 0, 1)">();
    IMigrationCommandExecutor executor </span>= db.GetService&lt;IMigrationCommandExecutor&gt;<span style="color: rgba(0, 0, 0, 1)">
();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取 DbContext 实例</span>
    DbContext context =<span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1)"> ((IDatabaseFacadeDependenciesAccessor)db).Context</span>;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取 Model 实例</span>
    IModel model =<span style="color: rgba(0, 0, 0, 1)"> context.Model;
    List</span>&lt;MigrationOperation&gt; operations = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 看看要删除哪些表</span>
    <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> entity <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> model.GetEntityTypes())
    {
      <strong><span style="background-color: rgba(255, 255, 0, 1)">DropTableOperation</span></strong> drpopr </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 被删除表的架构名</span>
            <span style="background-color: rgba(255, 255, 0, 1)">Schema =</span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1)"> entity.GetSchema()</span>,
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 被删除表的表名</span>
            <span style="background-color: rgba(255, 255, 0, 1)">Name = entity.GetTableName()</span>!<span style="color: rgba(0, 0, 0, 1)">
      };
      operations.Add(drpopr);
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 构建命令</span>
    <span style="color: rgba(0, 0, 255, 1)">var</span> commands =<span style="color: rgba(0, 0, 0, 1)"> generator.<strong><span style="background-color: rgba(255, 255, 0, 1)">Generate(operations, model)</span></strong>;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行命令</span>
<span style="color: rgba(0, 0, 0, 1)">    executor.<strong><span style="background-color: rgba(255, 255, 0, 1)">ExecuteNonQuery(commands, conn)</span></strong>;
}</span></pre>
</div>
<p>删除数据表,对应的迁移操作是 DropTable,所以实例化一个 DropTableOperation 对象,并设置要删除的表名(可能还有架构名)。接着生成 SQL 命令,最后执行它。完事。</p>
<p>为了兼容,还可以实现异步版本。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task RemoveTablesAsync(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> DatabaseFacade db)
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取DbContext实例</span>
    DbContext context =<span style="color: rgba(0, 0, 0, 1)"> ((IDatabaseFacadeDependenciesAccessor)db).Context;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取服务</span>
    IMigrationCommandExecutor executor =<span style="color: rgba(0, 0, 0, 1)"> context.
GetService</span>&lt;IMigrationCommandExecutor&gt;<span style="color: rgba(0, 0, 0, 1)">();
    IMigrationsSqlGenerator generator </span>=<span style="color: rgba(0, 0, 0, 1)"> context.
GetService</span>&lt;IMigrationsSqlGenerator&gt;<span style="color: rgba(0, 0, 0, 1)">();
    IRelationalConnection conn </span>= context.GetService&lt;IRelationalConnection&gt;<span style="color: rgba(0, 0, 0, 1)">();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 构建operation列表</span>
    List&lt;MigrationOperation&gt; operations = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除所有表</span>
    <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> ent <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> context.Model.GetEntityTypes())
    {
      operations.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> DropTableOperation()
      {
            Schema </span>=<span style="color: rgba(0, 0, 0, 1)"> ent.GetSchema(),
            Name </span>= ent.GetTableName()!<span style="color: rgba(0, 0, 0, 1)">
      });
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成命令</span>
    <span style="color: rgba(0, 0, 255, 1)">var</span> cmds =<span style="color: rgba(0, 0, 0, 1)"> generator.Generate(operations, context.Model);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行命令</span>
    <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> executor.ExecuteNonQueryAsync(cmds, conn);
}</span></pre>
</div>
<p>这里注意,Model 可能不只一个实体类,即不只一个表,所以要 foreach 逐个访问 IModel.GetEntityTypes 方法返回的实体类型集合。把实体对应的表都删除。</p>
<p>可以测试一下。假设用 SQL Server ,事先建一个数据库,里面没有表。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span>; } = <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.Empty;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span>? Major { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Age { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span>? Email { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}


</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyDbContext : DbContext
{

    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
      optionsBuilder.UseSqlServer(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">server=(localdb)\\MSSQLLOCALDB; database=Demo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> OnModelCreating(ModelBuilder modelBuilder)
    {
      modelBuilder.Entity</span>&lt;Student&gt;(et =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            et.HasKey(x </span>=&gt; x.ID).HasName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_Student</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            et.Property(x </span>=&gt; x.ID).<strong><span style="background-color: rgba(255, 255, 0, 1)">HasColumnName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sid</span><span style="color: rgba(128, 0, 0, 1)">"</span></span></strong><span style="color: rgba(0, 0, 0, 1)"><strong><span style="background-color: rgba(255, 255, 0, 1)">)</span></strong>
                .UseIdentityColumn(</span><span style="color: rgba(128, 0, 128, 1)">100</span>, <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
      });

    }
}</span></pre>
</div>
<p>模型配置时,让主键例的名字为 sid。</p>
<p>运行程序时,检查有没有数据表,没有就创建。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> dc = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MyDbContext();

</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">dc.Database.HasTables())
{
    dc.Database.CreateTables();
}</span></pre>
</div>
<p>若需要删除数据表,可以这样写:</p>
<div class="cnblogs_code">
<pre>dc.Database.RemoveTables();</pre>
</div>
<p>&nbsp;</p>
<p>怎么样,这样封装后是不是就和官方 API 那样方便?</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/tcjiaan/p/19007218
頁: [1]
查看完整版本: 【EF Core】为 DatabaseFacade 扩展“创建”与“删除”数据表功能