笑狂 發表於 2025-9-1 19:07:00

【EF Core】优化后的模型

<p>本文所讲述内容,大伙伴们不必要完全掌握,毕竟,dotnet ef 工具会帮助咱们生成相关代码。不过,为了让各位能够真正了解它,老周会做一次纯手搓代码。</p>
<p>所谓优化后的模型,相当于把实体的配置进行“硬编码”,程序会执行更少的代码来提升效率。放到实际代码编写上,这个活叫运行时模型,对应的类就是 RuntimeModel。与运行时模型相关的类型都是以“Runtime”开头的,对应着模型各个部分。例如:</p>
<p><span style="color: rgba(0, 51, 102, 1)">1、实体——&nbsp;RuntimeEntityType 类;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">2、属性——&nbsp;RuntimeProperty 类;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">3、主键——&nbsp;RuntimeKey 类;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">4、导航——&nbsp;RuntimeNavigation 类。导航属性使用专门的类,而不归类于 RuntimeProperty;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">5、外键——&nbsp;RuntimeForeignKey 类;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">6、索引——&nbsp;RuntimeIndex 类;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">7、其他,这里就不全列出了。</span></p>
<p>有大伙伴可能会想:都定义实体类了,为什么还要构建 Model 呢?因为这体类本身无法提供额外的信息,比如谁是主键,映射到哪个表哪个列,有哪些列是索引……而且,ef core 还要跟踪每个实体对象的状态,以便在必要时更新数据库。有太多的附加信息要处理,所以得有专门的类型去封装这些信息。</p>
<p>除了上面列出的专用运行时类型,EF Core 框架还用到另一个重要的东西去描述实体——Annotations(批注,或者叫注释)。EF Core 框架还定义了一个&nbsp;Annotation 类,专门保存批注信息。批注集合是一个字典,故一条批注是以 Name-Value 的形式存在的。Name 是字符串,Value 是任意类型。咱们在代码中能访问到的常用名称由&nbsp;RelationalAnnotationNames 公开,如&nbsp;TableName 字段可以返回表示表名称的字符串。另外,不同数据库提供者也可以公开专用的批注名称,如 SQL Server 数据库公开了&nbsp;SqlServerAnnotationNames,不过,此类位于&nbsp;Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal 命名空间,帮助文档上是查不到的,属于留给内部使用的。当然,咱们在代码中是可以访问的。</p>
<p>批注名称是用冒号来分隔层次的,有点像 ASP.NET Core 的配置树。比如,表示 SQL Server 标识列的批注是这样的:SqlServer:Identity,它的值是字符串,格式为 1,1 表示从1开始,增量为1。如果从1000开始增量为5,就是 1000,5(用逗号分隔)。</p>
<p>现在说回 RuntimeModel 类。实例化后,通过对应的方法调用来添加模型:</p>
<p><span style="color: rgba(0, 51, 102, 1)">1、AddEntityType 方法,向模型添加实体,返回&nbsp;RuntimeEntityType 实例;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">2、调用&nbsp;RuntimeEntityType 实例的&nbsp;AddProperty 方法添加属性,返回&nbsp;RuntimeProperty 实例;</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">3、调用&nbsp;RuntimeEntityType 实例的&nbsp;AddKey 方法创建主键,返回 <span class="mtk17">RuntimeKey 实例</span>,随后要调用&nbsp;SetPrimaryKey 方法设置主键;调用&nbsp;AddForeignKey 方法添加外键,返回&nbsp;RuntimeForeignKey 实例。</span></p>
<p><span style="color: rgba(0, 51, 102, 1)">……</span></p>
<p>总结一下思路:<span style="text-decoration: underline; color: rgba(255, 0, 0, 1); font-size: 15px"><strong>创模型,添实体,加属性,设主键,置外键,最后补批注</strong></span>。</p>
<p>上面就是本文所需的知识,运行时模型在建立时所调用的方法成员参数较多,而且不是所有参数都会用到,一般建议写上参数名。用命名参数就不必按顺序传参。这些参数等下面实际演练时再解释。</p>
<p>===============================================================================================</p>
<p>好了,理论上准备得差不多,接下来老周将纯手动打造一个运行时模型。由于运行时模型是不能创建数据库和表的,所以咱们采用 DB First 方案,先创建数据库。本次老周使用 SQL Server,使用以下脚本创建数据库(建议把脚本存为文件,后面写代码时可以参考):</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">USE</span><span style="color: rgba(0, 0, 0, 1)"> master;
</span><span style="color: rgba(0, 0, 255, 1)">GO</span>

<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)"> 创建数据库</span>
<span style="color: rgba(0, 0, 255, 1)">CREATE</span> <span style="color: rgba(0, 0, 255, 1)">DATABASE</span><span style="color: rgba(0, 0, 0, 1)"> ToyDB;
</span><span style="color: rgba(0, 0, 255, 1)">GO</span>
<span style="color: rgba(0, 0, 255, 1)">USE</span><span style="color: rgba(0, 0, 0, 1)"> ToyDB;
</span><span style="color: rgba(0, 0, 255, 1)">GO</span>

<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)"> 创建表</span>
<span style="color: rgba(0, 0, 255, 1)">CREATE</span> <span style="color: rgba(0, 0, 255, 1)">TABLE</span><span style="color: rgba(0, 0, 0, 1)"> dbo.tb_boys
(
    boy_id </span><span style="color: rgba(0, 0, 255, 1)">INT</span> <span style="color: rgba(255, 0, 255, 1)">IDENTITY</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">NVARCHAR</span>(<span style="color: rgba(128, 0, 0, 1); font-weight: bold">20</span>) <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">nick</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">NVARCHAR</span>(<span style="color: rgba(128, 0, 0, 1); font-weight: bold">20</span>) <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(0, 0, 255, 1)">CONSTRAINT</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">PK_boy_id</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">PRIMARY</span> <span style="color: rgba(0, 0, 255, 1)">KEY</span> (boy_id <span style="color: rgba(0, 0, 255, 1)">ASC</span><span style="color: rgba(0, 0, 0, 1)">)
);
</span><span style="color: rgba(0, 0, 255, 1)">GO</span>

<span style="color: rgba(0, 0, 255, 1)">CREATE</span> <span style="color: rgba(0, 0, 255, 1)">TABLE</span><span style="color: rgba(0, 0, 0, 1)"> dbo.tb_toys
(
    toy_id </span><span style="color: rgba(0, 0, 255, 1)">INT</span> <span style="color: rgba(255, 0, 255, 1)">IDENTITY</span>(<span style="color: rgba(128, 0, 0, 1); font-weight: bold">100</span>, <span style="color: rgba(128, 0, 0, 1); font-weight: bold">1</span>) <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)">,
    toy_desc </span><span style="color: rgba(0, 0, 255, 1)">NVARCHAR</span>(<span style="color: rgba(128, 0, 0, 1); font-weight: bold">50</span>) <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)">,
    toy_cate </span><span style="color: rgba(0, 0, 255, 1)">NVARCHAR</span>(<span style="color: rgba(128, 0, 0, 1); font-weight: bold">10</span>) <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)">,
    f_boy_id </span><span style="color: rgba(0, 0, 255, 1)">INT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,      <span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)"> 外键</span>
    <span style="color: rgba(0, 0, 255, 1)">CONSTRAINT</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">PK_toy_id</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">PRIMARY</span> <span style="color: rgba(0, 0, 255, 1)">KEY</span> (toy_id <span style="color: rgba(0, 0, 255, 1)">ASC</span><span style="color: rgba(0, 0, 0, 1)">),
    </span><span style="color: rgba(0, 0, 255, 1)">CONSTRAINT</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">FK_toy_boy</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">FOREIGN</span> <span style="color: rgba(0, 0, 255, 1)">KEY</span> (f_boy_id) <span style="color: rgba(0, 0, 255, 1)">REFERENCES</span> dbo.tb_boys (boy_id) <span style="color: rgba(0, 0, 255, 1)">ON</span> <span style="color: rgba(0, 0, 255, 1)">DELETE</span> <span style="color: rgba(0, 0, 255, 1)">CASCADE</span><span style="color: rgba(0, 0, 0, 1)">
);
</span><span style="color: rgba(0, 0, 255, 1)">GO</span></pre>
</div>
<p>tb_boys 表代表某男孩,tb_toys 表代表他拥有的玩具,每个 boy 在小时候都有自己喜欢的 toy,正如每个进城的农民工都怀揣着梦想一般;随着 boy 们的长大,许多 toy 逐渐被淡忘;随着时光的流逝,农民工们的梦已被风雨打碎,留下千丝万缕的遗恨与怅惘。</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)">class</span><span style="color: rgba(0, 0, 0, 1)"> Boy
{
    </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>? Nick { <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, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 导航属性</span>
    <strong><em><span style="color: rgba(0, 0, 255, 1)">public</span> ICollection&lt;Toy&gt; MyToys { <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)">new</span> List&lt;Toy&gt;</em></strong><span style="color: rgba(0, 0, 0, 1)"><strong><em>();</em></strong>
}

</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)"> Toy
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ToyID { <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> Desc { <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> Cate { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span>; } = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">经典玩具</span><span style="color: rgba(128, 0, 0, 1)">"</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>
    <strong><em><span style="color: rgba(0, 0, 255, 1)">public</span> Boy? TheBoy { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span></em></strong><span style="color: rgba(0, 0, 0, 1)"><strong><em>; }</em></strong>
}</span></pre>
</div>
<p>两个类都有导航属性,每个 Boy 的童年不可能只有一件玩具的,每件玩具专属于喜欢它的主人,因此这是一对多的关系。</p>
<p>好了,下面是重头戏,看看怎么构建 RuntimeModel。</p>
<p>1、实例化模型。</p>
<div class="cnblogs_code">
<pre>RuntimeModel model = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(
    skipDetectChanges: </span><span style="color: rgba(0, 0, 255, 1)">false</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开启更改跟踪</span>
    modelId: Guid.NewGuid(),    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 模型ID</span>
    entityTypeCount: <span style="color: rgba(128, 0, 128, 1)">2</span>,         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 模型中有两个实体类型</span>
    typeConfigurationCount: <span style="color: rgba(128, 0, 128, 1)">0</span>   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 未使用自定义类型转换</span>
);</pre>
</div>
<p>skipDetectChanges:99%选 false,因为我们希望跟踪模型的变更。modelId:模型的ID,GUID类型,随便分配,不会重复的。entityTypeCount:这个模型包含几个实体类型,这里明确指出(属于是硬编码了)。<span class="mtk17">typeConfigurationCount:保留默认0即可,实体的类型映射,这里咱们用不上,98%的情形也是用不上的。</span></p>
<p><span class="mtk17">2、添加 Boy 实体。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> boyEnt =<span style="color: rgba(0, 0, 0, 1)"> model.AddEntityType(
    name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DB.Boy</span><span style="color: rgba(128, 0, 0, 1)">"</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一般包含命名空间</span>
    type: <span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy),<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> CLR 类型</span>
    baseType: <span style="color: rgba(0, 0, 255, 1)">null</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 没有基类(指除Object以外)</span>
    propertyCount: <span style="color: rgba(128, 0, 128, 1)">3</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性个数,不含导航属性</span>
    navigationCount: <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 有一个导航属性</span>
    keyCount: <span style="color: rgba(128, 0, 128, 1)">1</span>         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 有一个主键</span>
);</pre>
</div>
<p>name 表示实体名称,一般用实体类的完整类型名(含命名空间+类名)。type 表示实体的类型 Type。<span class="mtk17">baseType:如果 Boy 有基类,要附上基类型。这里说的基类是除 Object 以外,此处,Boy 可以认为无基类型。<span class="mtk17">sharedClrType = false,不是共享的实体类型(多个实体共用一个CLR类型)。propertyCount 表示此实体包含属性个数,应为3,不包括导航属性,导航属性有家族背景,需要特殊对待。navigationCount 表示包含多少个导航属性,这里是一个。keyCount 表示实体有几个主键,这里一个。</span></span></p>
<p><span class="mtk17"><span class="mtk17">3、添加 Boy 实体的属性。注意,属性是加在 RuntimeEntity 中。</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> boyIdProp =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddProperty(
    name: nameof(Boy.ID),   </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性名</span>
    clrType: <span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span>),   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性类型</span>
    nullable: <span style="color: rgba(0, 0, 255, 1)">false</span>,      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 不为null
                            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引用CLR属性成员</span>
    propertyInfo: <span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, BindingFlags.
Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 无字段成员</span>
    fieldInfo: <span style="color: rgba(0, 0, 255, 1)">null</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, 0, 1)">    propertyAccessMode: PropertyAccessMode.PreferProperty,
    </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)">    valueGenerated: ValueGenerated.OnAdd,
    </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)">    afterSaveBehavior: PropertySaveBehavior.Throw,
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认值0</span>
    sentinel: <span style="color: rgba(128, 0, 128, 1)">0</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)"> SQL Server 值生成配置-标识列</span>
<span style="color: rgba(0, 0, 0, 1)">boyIdProp.AddAnnotation(SqlServerAnnotationNames.
ValueGenerationStrategy, SqlServerValueGenerationStrategy.
IdentityColumn);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nameProp =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddProperty(
    name: nameof(Boy.Name),
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
    nullable: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Name</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, BindingFlags.
Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
    maxLength: </span><span style="color: rgba(128, 0, 128, 1)">20</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)">    propertyAccessMode: PropertyAccessMode.PreferProperty
);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nickProp =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddProperty(
    name: nameof(Boy.Nick),
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
    nullable: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
    maxLength: </span><span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Boy).GetProperty(nameof(Boy.Nick),
BindingFlags.Public </span>| BindingFlags.DeclaredOnly |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.
Instance),
    propertyAccessMode: PropertyAccessMode.PreferProperty
);</span></pre>
</div>
<p>name:属性名,一般与 CLR 类型的属性名相同。clrType:属性值的类型。<span class="mtk17">propertyInfo:引用CLR属性的成员(通过反射来设置或读取值),设置值时要求用 set 访问器。<span class="mtk17">fieldInfo:存储属性值的字段成员,没有的话也可以为 null。<span class="mtk17">propertyAccessMode:表示 EF Core 如何访问属性,这是一个&nbsp;PropertyAccessMode 枚举,主要值有:</span></span></span></p>
<p><span class="mtk17" style="color: rgba(255, 0, 0, 1)"><span class="mtk17"><span class="mtk17">A、Field:必须通过字段来读写属性。使用该方式,实体类的属性必须定义隐藏字段。</span></span></span></p>
<p><span class="mtk17" style="color: rgba(255, 0, 0, 1)"><span class="mtk17"><span class="mtk17">B、FieldDuringConstruction:只在实体实例化(调用构造器)时才通字段访问属性。</span></span></span></p>
<p><span class="mtk17" style="color: rgba(255, 0, 0, 1)"><span class="mtk17"><span class="mtk17">C、Property:直接读写属性本身。</span></span></span></p>
<p><span class="mtk17" style="color: rgba(255, 0, 0, 1)"><span class="mtk17"><span class="mtk17">D、PreferField:先尝试通过字段来读写属性,如果没有,直接访问属性。</span></span></span></p>
<p><span class="mtk17" style="color: rgba(255, 0, 0, 1)"><span class="mtk17"><span class="mtk17">E:PreferFieldDuringConstruction:仅在实例构造时,尝试通过字段访问属性,若不行改为直接访问属性。</span></span></span></p>
<p><span class="mtk17" style="color: rgba(255, 0, 0, 1)"><span class="mtk17"><span class="mtk17">F:PreferProperty:通过属性直接访问。如果没有属性,或 get/set 不存在(通常不会这样),就改为通过字段读写。</span></span></span></p>
<p><span class="mtk17"><span class="mtk17"><span class="mtk17">上述枚举值要根据你的 propertyInfo 和 fieldInfo 参数来配置。</span></span></span></p>
<p><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17">nullable:表示此属性是否可为 null。<span class="mtk17">valueGenerated:值生成,如果是标识列,应选择&nbsp;ValueGenerated.OnAdd,插入数据时生成。<span class="mtk17">beforeSaveBehavior 和&nbsp;<span class="mtk17">afterSaveBehavior:指示属性值在写入数据库前后是否允许修改。对于标识列,afterSaveBehavior 参数可以设置为 Throw,即如果数据已存入数据库,那么后面就不让你修改(不能改生成的主键)。maxLength:一般用于字符类型,最大长度。unicode:一般用于字符类型,是否使用 Unicode。precision 和&nbsp;scale:一般用于浮点数,指定精度和位数。sentinel:如果属性未设置,给它一个默认值。</span></span></span></span></span></span></span></p>
<p><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17">注意:boyid是标识列,要用批注表明它是标识列。</span></span></span></span></span></span></span></p>
<div class="cnblogs_code">
<pre>boyIdProp.AddAnnotation(SqlServerAnnotationNames.ValueGenerationStrategy, <strong><span style="background-color: rgba(255, 255, 0, 1)">SqlServerValueGenerationStrategy.IdentityColumn</span></strong>);</pre>
</div>
<p>&nbsp;</p>
<p><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17"><span class="mtk17">4、给 Boy 添加主键。</span></span></span></span></span></span></span></p>
<div class="cnblogs_code">
<pre><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> boyKey =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddKey();
boyEnt.SetPrimaryKey(boyKey);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主键名称</span>
boyKey.<strong><span style="background-color: rgba(255, 255, 0, 1)">AddAnnotation(RelationalAnnotationNames.Name, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>)</span></strong>;</pre>
</div>
<p>主键的名称通过批注来设置。AddKey 方法引用一个属性列表,即哪些属性设置为键。</p>
<p>5、 Toy 实体的配置差不多。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> toyEnt =<span style="color: rgba(0, 0, 0, 1)"> model.AddEntityType(
    name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DB.Toy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    type: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Toy),
    baseType: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyCount: </span><span style="color: rgba(128, 0, 128, 1)">3</span>,         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性数量不含导航属性</span>
    navigationCount: <span style="color: rgba(128, 0, 128, 1)">1</span>,         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 导航属性个数</span>
    keyCount: <span style="color: rgba(128, 0, 128, 1)">1</span>,                <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主键个数</span>
    foreignKeyCount: <span style="color: rgba(128, 0, 128, 1)">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, 0, 1)">);

</span><span style="color: rgba(0, 0, 255, 1)">var</span> toyidProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
    name: nameof(Toy.ToyID),
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">),
    nullable: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
    valueGenerated: ValueGenerated.OnAdd,
    afterSaveBehavior: PropertySaveBehavior.Throw,
    propertyAccessMode: PropertyAccessMode.PreferProperty,
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Toy).GetProperty(nameof(Toy.ToyID),
BindingFlags.Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.
DeclaredOnly),
    sentinel: </span><span style="color: rgba(128, 0, 128, 1)">0</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, 0, 1)">toyidProp.AddAnnotation(SqlServerAnnotationNames.
ValueGenerationStrategy, SqlServerValueGenerationStrategy.
IdentityColumn);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> toydescProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
    name: nameof(Toy.Desc),
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
    nullable: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
    maxLength: </span><span style="color: rgba(128, 0, 128, 1)">50</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Toy).GetProperty(nameof(Toy.Desc),
BindingFlags.Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.
DeclaredOnly),
    propertyAccessMode: PropertyAccessMode.PreferProperty
);

</span><span style="color: rgba(0, 0, 255, 1)">var</span> toycateProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
    name: nameof(Toy.Cate),
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
    maxLength: </span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Toy).GetProperty(nameof(Toy.Cate),
BindingFlags.Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.
DeclaredOnly),
    propertyAccessMode: PropertyAccessMode.PreferProperty
);
</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> toytoboyIdProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
    name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">),
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">null</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 影子属性不需要引用属性成员</span>
    nullable: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
);</span></pre>
</div>
<p>boy_id 是影子属性,因为不需要与 CLR 类型映射,所以,propertyInfo 和 fieldInfo 参数不需要。虽然这货没有在实体类中定义,但 EF Core 内部会用一个字典来管理它。实际上 EF Core 为实体类存了不止一份值,比如“快照”。即当数据从数据库查询出来时会做一个快照,后面会用实体的值跟快照比较,以确定实体是否被修改了。</p>
<p>6、给 Toy 实体设置主键和外键。</p>
<div class="cnblogs_code">
<pre> <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> toyKey =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddKey();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主键名</span>
toyKey.AddAnnotation(RelationalAnnotationNames.Name, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_toy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
toyEnt.SetPrimaryKey(toyKey);
</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> toyforekey =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddForeignKey(
   properties: ,
   principalKey: boyKey,
   principalEntityType: boyEnt,
   deleteBehavior: DeleteBehavior.Cascade,
   unique: </span><span style="color: rgba(0, 0, 255, 1)">false</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)"> );
</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)"> toyforekey.AddAnnotation(RelationalAnnotationNames.Name,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">FK_toy_boy</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</pre>
</div>
<p>由于 Toy 表中会出现重复的 Boy ID,所以,AddForeignKey 方法的 unique 参数为 false。</p>
<p>7、导航属性,不管是 Boy 中的导航属性还是 Toy 中的,共用一个外键信息。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> boytotoyNav =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddNavigation(
    name: nameof(Boy.MyToys),
    <strong><span style="background-color: rgba(255, 255, 0, 1)">foreignKey: toyforekey</span></strong>,
    <strong><span style="background-color: rgba(255, 255, 0, 1)">onDependent: </span></strong></span><strong><span style="color: rgba(0, 0, 255, 1); background-color: rgba(255, 255, 0, 1)">false</span></strong><span style="color: rgba(0, 0, 0, 1)">,
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(ICollection&lt;Toy&gt;<span style="color: rgba(0, 0, 0, 1)">),
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Boy).GetProperty(nameof(Boy.MyToys),
BindingFlags.Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.
DeclaredOnly),
    fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyAccessMode: PropertyAccessMode.PreferProperty
);

</span><span style="color: rgba(0, 0, 255, 1)">var</span> toytoboyNav =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddNavigation(
    name: nameof(Toy.TheBoy),
    <span style="background-color: rgba(255, 255, 0, 1)"><strong>foreignKey: toyforekey</strong></span>,
    <strong><span style="background-color: rgba(255, 255, 0, 1)">onDependent: </span></strong></span><strong><span style="color: rgba(0, 0, 255, 1); background-color: rgba(255, 255, 0, 1)">true</span></strong><span style="color: rgba(0, 0, 0, 1)">,
    clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Boy),
    propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Toy).GetProperty(nameof(Toy.TheBoy),
BindingFlags.Public </span>| BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.
DeclaredOnly),
    fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
    propertyAccessMode: PropertyAccessMode.PreferProperty
);</span></pre>
</div>
<p>导航属性的添加和一般属性差不多。注意 onDependent 参数的设置,对于 Boy 来说,它应该是“父”,即主体(被 Toy 的外键引用),要设置为 false;而对于 Toy 而言为“子”,即依赖于主体,故 onDependent 为 true。</p>
<p>8、由于实体名和属性名都与数据库不同,所以还要做表、列的映射。这些也是通过批注完成的。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1、架构</span>
boyEnt.AddAnnotation(RelationalAnnotationNames.Schema, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
toyEnt.AddAnnotation(RelationalAnnotationNames.Schema, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</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)"> 2、表名</span>
boyEnt.AddAnnotation(RelationalAnnotationNames.TableName, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_boys</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
toyEnt.AddAnnotation(RelationalAnnotationNames.TableName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_toys</span><span style="color: rgba(128, 0, 0, 1)">"</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)"> 3、列名</span>
<span style="color: rgba(0, 0, 0, 1)">boyIdProp.AddAnnotation(RelationalAnnotationNames.ColumnName,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
nameProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
nickProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nick</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

toyidProp.AddAnnotation(RelationalAnnotationNames.ColumnName,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">toy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
toydescProp.AddAnnotation(RelationalAnnotationNames.ColumnName,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">toy_desc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
toycateProp.AddAnnotation(RelationalAnnotationNames.ColumnName,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">toy_cate</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
toytoboyIdProp.AddAnnotation(RelationalAnnotationNames.ColumnName,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">f_boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</pre>
</div>
<p>&nbsp;</p>
<p>好了,模型就配好了。下面是完整代码。老周用了一个静态类来封装(你也可以像 dotnet-ef 工具那样,从 RuntimeModel 类派生)。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">#pragma</span> warning disable EF1001 <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Internal EF Core API usage.</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)">class</span><span style="color: rgba(0, 0, 0, 1)"> ModelHelpers
{
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeModel _model;

    </span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> ModelHelpers()
    {
      _model </span>=<span style="color: rgba(0, 0, 0, 1)"> BuildRuntimeModel();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> RuntimeModel DemoModel =&gt;<span style="color: rgba(0, 0, 0, 1)"> _model;

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeModel BuildRuntimeModel()
    {
      RuntimeModel model </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(
            skipDetectChanges: </span><span style="color: rgba(0, 0, 255, 1)">false</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开启更改跟踪</span>
            modelId: Guid.NewGuid(),    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 模型ID</span>
            entityTypeCount: <span style="color: rgba(128, 0, 128, 1)">2</span>,         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 模型中有两个实体类型</span>
            typeConfigurationCount: <span style="color: rgba(128, 0, 128, 1)">0</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)">      );

      </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> boyEnt =<span style="color: rgba(0, 0, 0, 1)"> model.AddEntityType(
            name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DB.Boy</span><span style="color: rgba(128, 0, 0, 1)">"</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一般包含命名空间</span>
            type: <span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy),<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> CLR 类型</span>
            baseType: <span style="color: rgba(0, 0, 255, 1)">null</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 没有基类(指除Object以外)</span>
            propertyCount: <span style="color: rgba(128, 0, 128, 1)">3</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性个数,不含导航属性</span>
            navigationCount: <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 有一个导航属性</span>
            keyCount: <span style="color: rgba(128, 0, 128, 1)">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, 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> boyIdProp =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddProperty(
            name: nameof(Boy.ID),   </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性名</span>
            clrType: <span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span>),   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性类型</span>
            nullable: <span style="color: rgba(0, 0, 255, 1)">false</span>,      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 不为null
                                    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引用CLR属性成员</span>
            propertyInfo: <span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 无字段成员</span>
            fieldInfo: <span style="color: rgba(0, 0, 255, 1)">null</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, 0, 1)">            propertyAccessMode: PropertyAccessMode.PreferProperty,
            </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)">            valueGenerated: ValueGenerated.OnAdd,
            </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)">            afterSaveBehavior: PropertySaveBehavior.Throw,
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认值0</span>
            sentinel: <span style="color: rgba(128, 0, 128, 1)">0</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)"> SQL Server 值生成配置-标识列</span>
<span style="color: rgba(0, 0, 0, 1)">      boyIdProp.AddAnnotation(SqlServerAnnotationNames.ValueGenerationStrategy, SqlServerValueGenerationStrategy.IdentityColumn);

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> nameProp =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddProperty(
            name: nameof(Boy.Name),
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
            nullable: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            maxLength: </span><span style="color: rgba(128, 0, 128, 1)">20</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)">            propertyAccessMode: PropertyAccessMode.PreferProperty
      );

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> nickProp =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddProperty(
            name: nameof(Boy.Nick),
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
            nullable: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
            maxLength: </span><span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy).GetProperty(nameof(Boy.Nick), BindingFlags.Public | BindingFlags.DeclaredOnly |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.Instance),
            propertyAccessMode: PropertyAccessMode.PreferProperty
      );

      </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> boyKey =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddKey();
      boyEnt.SetPrimaryKey(boyKey);
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主键名称</span>
      boyKey.AddAnnotation(RelationalAnnotationNames.Name, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</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)">var</span> toyEnt =<span style="color: rgba(0, 0, 0, 1)"> model.AddEntityType(
            name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DB.Toy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            type: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Toy),
            baseType: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyCount: </span><span style="color: rgba(128, 0, 128, 1)">3</span>,         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性数量不含导航属性</span>
            navigationCount: <span style="color: rgba(128, 0, 128, 1)">1</span>,         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 导航属性个数</span>
            keyCount: <span style="color: rgba(128, 0, 128, 1)">1</span>,                <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主键个数</span>
            foreignKeyCount: <span style="color: rgba(128, 0, 128, 1)">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, 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> toyidProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
            name: nameof(Toy.ToyID),
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">),
            nullable: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
            valueGenerated: ValueGenerated.OnAdd,
            afterSaveBehavior: PropertySaveBehavior.Throw,
            propertyAccessMode: PropertyAccessMode.PreferProperty,
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Toy).GetProperty(nameof(Toy.ToyID), BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            sentinel: </span><span style="color: rgba(128, 0, 128, 1)">0</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, 0, 1)">      toyidProp.AddAnnotation(SqlServerAnnotationNames.ValueGenerationStrategy, SqlServerValueGenerationStrategy.IdentityColumn);

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> toydescProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
            name: nameof(Toy.Desc),
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
            nullable: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
            maxLength: </span><span style="color: rgba(128, 0, 128, 1)">50</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Toy).GetProperty(nameof(Toy.Desc), BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            propertyAccessMode: PropertyAccessMode.PreferProperty
      );

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> toycateProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
            name: nameof(Toy.Cate),
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">),
            maxLength: </span><span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Toy).GetProperty(nameof(Toy.Cate), BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            propertyAccessMode: PropertyAccessMode.PreferProperty
      );
      </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> toytoboyIdProp =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddProperty(
            name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">),
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">null</span>,   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 影子属性不需要引用属性成员</span>
            nullable: <span style="color: rgba(0, 0, 255, 1)">true</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)">var</span> toyKey =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddKey();
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主键名</span>
      toyKey.AddAnnotation(RelationalAnnotationNames.Name, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_toy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      toyEnt.SetPrimaryKey(toyKey);
      </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> toyforekey =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddForeignKey(
            properties: ,
            principalKey: boyKey,
            principalEntityType: boyEnt,
            deleteBehavior: DeleteBehavior.Cascade,
            unique: </span><span style="color: rgba(0, 0, 255, 1)">false</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)">      );
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 外键名称</span>
      toyforekey.AddAnnotation(RelationalAnnotationNames.Name, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">FK_toy_boy</span><span style="color: rgba(128, 0, 0, 1)">"</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)">var</span> boytotoyNav =<span style="color: rgba(0, 0, 0, 1)"> boyEnt.AddNavigation(
            name: nameof(Boy.MyToys),
            foreignKey: toyforekey,
            onDependent: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(ICollection&lt;Toy&gt;<span style="color: rgba(0, 0, 0, 1)">),
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Boy).GetProperty(nameof(Boy.MyToys), BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyAccessMode: PropertyAccessMode.PreferProperty
      );
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> toytoboyNav =<span style="color: rgba(0, 0, 0, 1)"> toyEnt.AddNavigation(
            name: nameof(Toy.TheBoy),
            foreignKey: toyforekey,
            onDependent: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
            clrType: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Boy),
            propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Toy).GetProperty(nameof(Toy.TheBoy), BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
            fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
            propertyAccessMode: PropertyAccessMode.PreferProperty
      );

      </span><span style="color: rgba(0, 128, 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, 128, 0, 1)"> 1、架构</span>
      boyEnt.AddAnnotation(RelationalAnnotationNames.Schema, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      toyEnt.AddAnnotation(RelationalAnnotationNames.Schema, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</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)"> 2、表名</span>
      boyEnt.AddAnnotation(RelationalAnnotationNames.TableName, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_boys</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      toyEnt.AddAnnotation(RelationalAnnotationNames.TableName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_toys</span><span style="color: rgba(128, 0, 0, 1)">"</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)"> 3、列名</span>
      boyIdProp.AddAnnotation(RelationalAnnotationNames.ColumnName, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      nameProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      nickProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nick</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      toyidProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">toy_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      toydescProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">toy_desc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      toycateProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">toy_cate</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      toytoboyIdProp.AddAnnotation(RelationalAnnotationNames.ColumnName, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">f_boy_id</span><span style="color: rgba(128, 0, 0, 1)">"</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)">return</span><span style="color: rgba(0, 0, 0, 1)"> model;
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">#pragma</span> warning restore EF1001 <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Internal EF Core API usage.</span></pre>
</div>
<p>&nbsp;</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)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoContext : 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 ob)
    {
      ob.UseSqlServer(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">server=你的服务器; database=你的数据库</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
            .LogTo(o </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> Console.WriteLine(o))
            .EnableSensitiveDataLogging(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
            .<strong><span style="background-color: rgba(255, 255, 0, 1)">UseModel(ModelHelpers.DemoModel)</span></strong>;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DbSet&lt;Boy&gt; BoySet { <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> DbSet&lt;Toy&gt; ToySet { <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></pre>
</div>
<p>熟悉的配方,不用多解释了。</p>
<p>&nbsp;</p>
<p>下面是测试代码。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span> DemoContext dc = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();

</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">dc.BoySet.Any())
{
    Boy b1 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
    {
      Name </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">小张</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Nick </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">灰太狼</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    };
    b1.MyToys.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
    {
      Desc </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">电动风车</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Cate </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">电动玩具</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    });
    b1.MyToys.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
    {
      Desc </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">米老鼠高压水枪</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Cate </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">气动玩具</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    });
    dc.BoySet.Add(b1);

    Boy b2 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Boy
    {
      Nick </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">哈巴狗</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Name </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">小李</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    };
    b2.MyToys.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span>() { Desc = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">库洛牌</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Cate = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">卡牌</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> });
    b2.MyToys.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span>() { Desc = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">yoyo</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Cate = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">光电玩具</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> });
    dc.BoySet.Add(b2);

    </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)">    dc.SaveChanges();
}</span></pre>
</div>
<p>插入的数据如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/367389/202509/367389-20250901113120661-1386254090.png" alt="image" width="322" height="71" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/367389/202509/367389-20250901113157155-566906774.png" alt="image" width="536" height="138" loading="lazy"></p>
<p>&nbsp;</p>
<p>================================================================================================</p>
<p>上面内容是不实用的,只是方便学习,下面老周演示一下如何用 dotnet-ef 工具生成运行时模型。这才是咱们在实际项目中要用的(除非特殊需求,要自己去写)。</p>
<p>1、新建一个控制台项目。</p>
<div class="cnblogs_code">
<pre>dotnet <span style="color: rgba(0, 0, 255, 1)">new</span> console -n Demo -o .</pre>
</div>
<p>2、添加要用的包。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">dotnet add package microsoft.entityframeworkcore
dotnet add package microsoft.entityframeworkcore.sqlserver</span></pre>
</div>
<p>3、要使用 dotnet-ef 工具,还得添加设计时包。</p>
<div class="cnblogs_code">
<pre>dotnet add package microsoft.entityframeworkcore.design</pre>
</div>
<p>添加完毕后,项目应该引用了三个库:</p>
<div class="cnblogs_code">
<pre>&lt;ItemGroup&gt;
    &lt;PackageReference Include=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft.EntityFrameworkCore</span><span style="color: rgba(128, 0, 0, 1)">"</span> Version=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">9.0.8</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
    &lt;PackageReference Include=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft.EntityFrameworkCore.Design</span><span style="color: rgba(128, 0, 0, 1)">"</span> Version=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">9.0.8</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
      &lt;IncludeAssets&gt;runtime; build; native; contentfiles; analyzers; buildtransitive&lt;/IncludeAssets&gt;
      &lt;PrivateAssets&gt;all&lt;/PrivateAssets&gt;
    &lt;/PackageReference&gt;
    &lt;PackageReference Include=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft.EntityFrameworkCore.SqlServer</span><span style="color: rgba(128, 0, 0, 1)">"</span> Version=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">9.0.8</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
&lt;/ItemGroup&gt;</pre>
</div>
<p>设计时库被设置为“私有资产”,你在代码中无法访问。如果你在代码要用,最简单方法是把 IncludeAssets、PrivateAssets 节点干掉。</p>
<p>&nbsp;</p>
<p>4、定义实体类。</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)"> Light
{
    </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(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> Guid LightID { <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(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)">string</span>[] Color { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span>; } = [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">白</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 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(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)">float</span> Power { <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(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)"> 是否为 RGB LED 灯
    </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)">bool</span>? IsRGBLed { <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></pre>
</div>
<p>5、定义上下文类。</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)"> MyDbContext : DbContext
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> MyDbContext(DbContextOptions&lt;MyDbContext&gt;<span style="color: rgba(0, 0, 0, 1)"> options)
      : </span><span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">(options)
    {

    }

    </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)">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 mb)
    {
      mb.Entity</span>&lt;Light&gt;().HasKey(e =&gt; e.LightID).HasName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_light_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      mb.Entity</span>&lt;Light&gt;().Property(g =&gt;<span style="color: rgba(0, 0, 0, 1)"> g.LightID)
            .ValueGeneratedOnAdd();
      mb.Entity</span>&lt;Light&gt;().Property(x =&gt;<span style="color: rgba(0, 0, 0, 1)"> x.Color)
            .HasMaxLength(</span><span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">).IsRequired();
      mb.Entity</span>&lt;Light&gt;().Property(s =&gt;<span style="color: rgba(0, 0, 0, 1)"> s.Power)
            .HasPrecision(</span><span style="color: rgba(128, 0, 128, 1)">5</span>, <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
      mb.Entity</span>&lt;Light&gt;().ToTable(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span>, tb =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            tb.Property(a </span>=&gt; a.LightID).HasColumnName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">light_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            tb.Property(a </span>=&gt; a.Color).HasColumnName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">light_colors</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            tb.Property(a </span>=&gt; a.Power).HasColumnName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">light_pwr</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            tb.Property(a </span>=&gt; a.IsRGBLed).HasColumnName(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">is_rgbled</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)">public</span> DbSet&lt;Light&gt; Lights { <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></pre>
</div>
<p>6、定义一个类,实现&nbsp;IDesignTimeDbContextFactory 接口。在执行 dotnet ef 命令时可以用来创建 MyDbContext 实例(设计阶段专用)。</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> CustDesigntimeFactory : IDesignTimeDbContextFactory&lt;MyDbContext&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> MyDbContext CreateDbContext(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建选项</span>
      DbContextOptions&lt;MyDbContext&gt; options = <span style="color: rgba(0, 0, 255, 1)">new</span> DbContextOptionsBuilder&lt;MyDbContext&gt;<span style="color: rgba(0, 0, 0, 1)">()
            .UseSqlServer(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">server=你的服务器; database=你的数据库</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
            .LogTo(s </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> Console.WriteLine(s))
            .Options;
      </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)">return</span> <strong><span style="color: rgba(0, 0, 255, 1); background-color: rgba(255, 255, 0, 1)">new</span></strong><span style="color: rgba(0, 0, 0, 1)"><strong><span style="background-color: rgba(255, 255, 0, 1)"> MyDbContext(options)</span></strong>;
    }
}</span></pre>
</div>
<p>代码不用往下写了,这个时候,就可以用 ef 工具生成优化的模型了。</p>
<div class="cnblogs_code">
<pre>dotnet ef dbcontext optimize -c <em><span style="background-color: rgba(255, 255, 153, 1)">MyDbContext</span></em> -n <em><span style="background-color: rgba(255, 255, 153, 1)">DB</span></em> -o <em><span style="background-color: rgba(255, 255, 153, 1)">DB</span></em></pre>
</div>
<p>-c 指定要用到的 DbContext 子类,这里可以省略,工具会自动搜索项目中的 MyDbContext 类。-n 表示生成代码使用的命名空间,这里指定了 DB。-o 表示生成的代码文件存放到哪个目录中,这里存到 DB 目录下(相对于项目目录)。</p>
<p>工具先编译一下项目,然后实例化 MyDbContext 类,执行一遍模型配置,最终生成相关代码。</p>
<p><img src="https://img2024.cnblogs.com/blog/367389/202509/367389-20250901175931266-395257124.png" alt="image" width="344" height="141" loading="lazy"></p>
<p>&nbsp;MyDbContextModel.cs 和&nbsp;MyDbContextModelBuilder.cs 都是模型类相关。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> DB
{
    <strong><span style="background-color: rgba(255, 255, 153, 1)">
</span></span></strong>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyDbContextModel : RuntimeModel
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> _useOldBehavior31751 =<span style="color: rgba(0, 0, 0, 1)">
            System.AppContext.TryGetSwitch(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft.EntityFrameworkCore.Issue31751</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">var</span> enabled31751) &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> enabled31751;

      </span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> MyDbContextModel()
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> model = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MyDbContextModel();

            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (_useOldBehavior31751)
            {
                model.Initialize();
            }
            </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
            {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> thread = <span style="color: rgba(0, 0, 255, 1)">new</span> System.Threading.Thread(RunInitialization, <span style="color: rgba(128, 0, 128, 1)">10</span> * <span style="color: rgba(128, 0, 128, 1)">1024</span> * <span style="color: rgba(128, 0, 128, 1)">1024</span><span style="color: rgba(0, 0, 0, 1)">);
                thread.Start();
                thread.Join();

                </span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> RunInitialization()
                {
                  model.Initialize();
                }
            }

            model.Customize();
            _instance </span>=<span style="color: rgba(0, 0, 0, 1)"> (MyDbContextModel)model.FinalizeModel();
      }

      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> MyDbContextModel _instance;
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> IModel Instance =&gt;<span style="color: rgba(0, 0, 0, 1)"> _instance;

      </span><span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Initialize();

      </span><span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Customize();
    }
}</span></pre>
</div>
<p>注意,MyDbContextModel 类是 partial 的,意味着你可以自定义扩展它,只要写在其他文件中,若模型修改了,重新运行 ef dbcontext 命令也不会被覆盖。</p>
<p>此类应用了&nbsp;DbContextAttribute 特性类,表明此模型与 MyDbContext 关联。</p>
<p>LightEntityType.cs 文件就是配置 Light 实体的代码了,看看里面有啥。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> LightEntityType
    {
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> runtimeEntityType =<span style="color: rgba(0, 0, 0, 1)"> model.<strong><span style="background-color: rgba(255, 255, 0, 1)">AddEntityType</span></strong>(
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DataBS.Light</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)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Light),
                baseEntityType,
                propertyCount: </span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">,
                keyCount: </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> lightID =<span style="color: rgba(0, 0, 0, 1)"> runtimeEntityType.<span style="background-color: rgba(255, 255, 0, 1)">AddProperty</span>(
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">LightID</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)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(Guid),
                propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">LightID</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetField(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&lt;LightID&gt;k__BackingField</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.NonPublic | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                valueGenerated: ValueGenerated.OnAdd,
                afterSaveBehavior: PropertySaveBehavior.Throw,
                sentinel: </span><span style="color: rgba(0, 0, 255, 1)">new</span> Guid(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">00000000-0000-0000-0000-000000000000</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)">var</span> overrides = <span style="color: rgba(0, 0, 255, 1)">new</span> StoreObjectDictionary&lt;RuntimeRelationalPropertyOverrides&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> lightIDTb_lights = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeRelationalPropertyOverrides(
                lightID,
                StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</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)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">light_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            overrides.Add(StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">), lightIDTb_lights);
            lightID.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:RelationalOverrides</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, overrides);

            lightID.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SqlServer:ValueGenerationStrategy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, SqlServerValueGenerationStrategy.None);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> color =<span style="color: rgba(0, 0, 0, 1)"> runtimeEntityType.<span style="background-color: rgba(255, 255, 0, 1)">AddProperty</span>(
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Color</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)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[]),
                propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Color</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetField(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&lt;Color&gt;k__BackingField</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.NonPublic | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                maxLength: </span><span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> overrides0 = <span style="color: rgba(0, 0, 255, 1)">new</span> StoreObjectDictionary&lt;RuntimeRelationalPropertyOverrides&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> colorTb_lights = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeRelationalPropertyOverrides(
                color,
                StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</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)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">light_colors</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            overrides0.Add(StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">), colorTb_lights);
            color.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:RelationalOverrides</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, overrides0);

            color.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SqlServer:ValueGenerationStrategy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, SqlServerValueGenerationStrategy.None);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> isRGBLed =<span style="color: rgba(0, 0, 0, 1)"> runtimeEntityType.<span style="background-color: rgba(255, 255, 0, 1)">AddProperty</span>(
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsRGBLed</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)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">bool</span>?<span style="color: rgba(0, 0, 0, 1)">),
                propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsRGBLed</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetField(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&lt;IsRGBLed&gt;k__BackingField</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.NonPublic | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                nullable: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> overrides1 = <span style="color: rgba(0, 0, 255, 1)">new</span> StoreObjectDictionary&lt;RuntimeRelationalPropertyOverrides&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> isRGBLedTb_lights = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeRelationalPropertyOverrides(
                isRGBLed,
                StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</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)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">is_rgbled</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            overrides1.Add(StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">), isRGBLedTb_lights);
            isRGBLed.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:RelationalOverrides</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, overrides1);

            isRGBLed.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SqlServer:ValueGenerationStrategy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, SqlServerValueGenerationStrategy.None);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> power =<span style="color: rgba(0, 0, 0, 1)"> runtimeEntityType.<span style="background-color: rgba(255, 255, 0, 1)">AddProperty</span>(
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Power</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)">typeof</span>(<span style="color: rgba(0, 0, 255, 1)">float</span><span style="color: rgba(0, 0, 0, 1)">),
                propertyInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Power</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.Public | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                fieldInfo: </span><span style="color: rgba(0, 0, 255, 1)">typeof</span>(Light).GetField(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&lt;Power&gt;k__BackingField</span><span style="color: rgba(128, 0, 0, 1)">"</span>, BindingFlags.NonPublic | BindingFlags.Instance |<span style="color: rgba(0, 0, 0, 1)"> BindingFlags.DeclaredOnly),
                precision: </span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">,
                scale: </span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">,
                sentinel: 0f);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> overrides2 = <span style="color: rgba(0, 0, 255, 1)">new</span> StoreObjectDictionary&lt;RuntimeRelationalPropertyOverrides&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> powerTb_lights = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeRelationalPropertyOverrides(
                power,
                StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</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)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">light_pwr</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            overrides2.Add(StoreObjectIdentifier.Table(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">), powerTb_lights);
            power.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:RelationalOverrides</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, overrides2);

            power.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SqlServer:ValueGenerationStrategy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, SqlServerValueGenerationStrategy.None);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> key =<span style="color: rgba(0, 0, 0, 1)"> runtimeEntityType.<span style="background-color: rgba(255, 255, 0, 1)">AddKey</span>(
                </span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">[] { lightID });
            runtimeEntityType.SetPrimaryKey(key);
            key.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:Name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PK_light_id</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)">return</span><span style="color: rgba(0, 0, 0, 1)"> runtimeEntityType;
      }

      </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><span style="color: rgba(0, 0, 0, 1)"> CreateAnnotations(RuntimeEntityType runtimeEntityType)
      {
            runtimeEntityType.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:FunctionName</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
            <span style="background-color: rgba(255, 255, 0, 1)">runtimeEntityType.AddAnnotation(</span></span><span style="background-color: rgba(255, 255, 0, 1)"><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:Schema</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dbo</span><span style="color: rgba(128, 0, 0, 1)">"</span></span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1)">);</span>
            runtimeEntityType.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:SqlQuery</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
            <span style="background-color: rgba(255, 255, 0, 1)">runtimeEntityType.AddAnnotation(</span></span><span style="background-color: rgba(255, 255, 0, 1)"><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:TableName</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tb_lights</span><span style="color: rgba(128, 0, 0, 1)">"</span></span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1)">);</span>
            runtimeEntityType.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:ViewName</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
            runtimeEntityType.AddAnnotation(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Relational:ViewSchema</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);

            Customize(runtimeEntityType);
      }

      </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Customize(RuntimeEntityType runtimeEntityType);
    }</span></pre>
</div>
<p>是不是和咱们前文中自己手写的很像?所以,实际开发中咱们是不用自己动手写的,用工具生成即可。</p>
<p>MyDbContextAssemblyAttributes.cs 文件有一个程序集级别的特性应用。</p>
<div class="cnblogs_code">
<pre></pre>
</div>
<p>有了这个特性,EF Core 就能自己查找 RuntimeModel,不需要调用&nbsp;DbContextOptionsBuilder 的 UseModel 方法来添加外部模型了。</p>
<p>&nbsp;</p>
<p>顺便总结一下,EF Core 框架是按这个顺序查找模型的:</p>
<p>1、UseModel 方法指定的外部模型(请看上一篇水文),如果从选项类设置了,就用这个模型;</p>
<p>2、如果选项类没有用 UseModel 方法设置外部模型,那就找一下有没 dotnet-ef 工具生成的模型(就是咱们刚刚做的事)。如果有,就用它,原理是根据程序集上应用的&nbsp;DbContextModelAttribute 特性找到生成的模型类,如本例中的&nbsp;MyDbContextModel。接着查找模型类中名为 Instance 的静态属性,读取这个属性的值,就能获取模型实例了。显然,运行时模型实例是静态的,即只实例化一次。</p>
<p>可以看看源代码:</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">static</span> IModel?<span style="color: rgba(0, 0, 0, 1)"> FindCompiledModel(Type contextType)
{
   </span><span style="color: rgba(0, 0, 255, 1)">var</span> contextAssembly =<span style="color: rgba(0, 0, 0, 1)"> contextType.Assembly;
   IModel</span>? model = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
   </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> modelAttribute <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> contextAssembly.
GetCustomAttributes</span>&lt;<span style="background-color: rgba(255, 255, 0, 1)">DbContextModelAttribute</span>&gt;<span style="color: rgba(0, 0, 0, 1)">())
   {
         </span><span style="color: rgba(0, 0, 255, 1)">if</span> (modelAttribute.ContextType !=<span style="color: rgba(0, 0, 0, 1)"> contextType)
         {
             </span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
         }
         </span><span style="color: rgba(0, 0, 255, 1)">var</span> modelType =<span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1)"> modelAttribute.ModelType</span>;
         </span><span style="color: rgba(0, 0, 255, 1)">var</span> instanceProperty = modelType.<span style="background-color: rgba(255, 255, 0, 1)">GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Instance</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
BindingFlags.Public </span>|</span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1)"> BindingFlags.Static)</span>;
         </span><span style="color: rgba(0, 0, 255, 1)">if</span> (instanceProperty == <span style="color: rgba(0, 0, 255, 1)">null</span>
             || instanceProperty.PropertyType != <span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(IModel))
         {
             </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> InvalidOperationException(CoreStrings.
CompiledModelMissingInstance(modelType.DisplayName
()));
         }
         </span><span style="color: rgba(0, 0, 255, 1)">if</span> (model != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
         {
             </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> InvalidOperationException(
               CoreStrings.CompiledModelDuplicateAttribute(
                     contextAssembly.FullName, contextType.
DisplayName()));
         }
         model </span>= <span style="background-color: rgba(255, 255, 0, 1)">(IModel)instanceProperty.GetValue(<span style="color: rgba(0, 0, 255, 1)">null</span>)</span>!<span style="color: rgba(0, 0, 0, 1)">;
   }
   </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> model;
}</span></pre>
</div>
<p>3、如果找不到 ef 工具生成的运行时模型,就调用内部模型构建,即调用 DbContext 的 OnModelCreating 方法以设计时形态构建模型。构建完毕后,通过预置约定&nbsp;RuntimeModelConvention 生成 RuntimeModel。当然了,前面多次提到,如果要在代码中创建数据库或迁移,是不使用运行时模型的,而是直接跑 OnModelCreating 方法的配置代码,当然,预置约定也会全部跑一遍。</p>
<p>&nbsp;</p>
<p>=========================================================================================</p>
<p>上周六,老周作为外三路辅助招聘大师,和两家企业的内部招聘人员交流。他们抱怨说现在的码农怎么回事,技术水平咋感觉一代不如一代,是不是现在工具太好用了,还有 AI 辅助,反而让他变菜了?就此老周也发表了自己的荒唐观点:</p>
<p><span style="color: rgba(0, 0, 128, 1)">过度依赖 AI 以及其他工具并不是他们菜的原因,而是他们菜的结果。工具本身没啥,爱用就用,不爱用就不用,就是辅助的,真正干事的还是人类。但核心事件是——他们就是菜,从骨子里透出来的菜,而且,菜还不练!整天做出一副要改革职场的屌样。你们又不是缺人缺到项目写不动的程度,真要是那么缺人,要不分一点给我,我帮你做。既然招不到人项目还是能继续干的,那就不着急,总能找到不菜的人。我不相信国内的程序猿全都那么菜。</span></p>
<p>如果你想老周分析一下,现在很多码仔那么菜的原因,那对不起了,老周又要说你们不爱听的话了。那些人就是被当今网络环境忽悠成菜鸟的。如果你在十几年前关注过一些培训班,不管培训钢琴、古筝、编程啥的,它们很喜欢一句口号——“XXX 内速成”,比如一个月内速成,三个月内速成。有脑子都知道是P话,但架不住许多驴子和家长会相信。后来央视曝光过,现在“速成”二字很少见了。但是,这些骗子仍旧屎心不改,换个模式接着忽悠。于是出现了学 XXX 拿 YYY 万高薪。不出意外,也有许多驴子相信了。当初还有些大学森问过老周,报不报这些?老周说:“你学校没得学吗?图书馆地震了吗?没开课吗?何必呢?那些‘老师’估计比你们学校的老师还菜”。要是你听了它们的鬼话,估计连面试都过不了,还想什么高薪。</p>
<p>在网上曾看到过一个笑话,A说:上次有个哥们来我们这面试,问了一个 C++ 虚函数表的问题,那家伙直跑了。简历上还写着“精通C++”。然后下面,B网友说“那是北大青X出来的吧”。</p>
<p>现在,坑人模式升级了,不,准确来说没升级,2005 年前后网上就有这些货了,只是那时候没有短视频,也没那么多人上网。现在短视频里教别人编程的,老周可以不客气的说:全是坑人的(包括老周自己录的,也是忽悠你的)。</p>
<p>在老周心中,什么样的视频教程是合格的?如果各位和老周一样足够老的话,一定看过孙鑫老师的 C++ 视频,20集,时长惊人,含金量不用多说。说简单点,视频教程要达到这种层次,才是有观看价值的。你看看现在各种短视频里面,有这种水平的吗?</p>
<p>还是看书好,就算有些书内容不怎么样,但至少内容是相对全面系统化的,视频、博文、贴子可以作为辅助学习。</p>
<p>王经理说老周面试时太仁慈,只问些基础知识,从来不问项目经验。我就给王经理解释了一通。实际应用中,个个项目是不同的,就是有个别的书本会讲项目上的事,但对于实际工作中还是没多大意义的。工作经验是靠总结,每个人的想法都可能不一样,没办法作为知识点让你一条一条去学,学了也没用。其实项目经验这东西,把你放项目里面呆几个月基本就有经验了,不用学的,自然就会。</p>
<p>可是,技术和基础知识则不同,这些都必须去学的。你得先把这一关过了,项目上要安排你做什么你随机应变就行,你只要技术够硬,就马上就能想到这个东西要用什么解决。比如这里是不是要用 Web API 实现,那里是不是要用 SHAXXX 加密一下,那里是不是要用到压缩数据,某个窗口是不是要开后台线程处理,某个工序是不是要创建一个队列来排单……</p>
<p>要是你基础知识没学好,我叫你改一下那个页面,登录加密加个下拉表列,可以选 MD5、SHA1、SHA256 算法,然后提交前用对应的算法 Hash 一下密码。这里你完全可以用反射来做,.NET 的 MD5 等类,都有一个静态的 Create 方法……懂我的意思了吧。但是,如果你连反射是啥都不知道,自然不会想到这样解决,可能会用多 if 语句处理。虽说不是不行,但不如反射来得通用且简便。</p>
<p>说多了,其实就是现在很多人不愿意去实践,学了不去试,懒得动手,等真正要用的时候就不知所措了。</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/tcjiaan/p/19067778
頁: [1]
查看完整版本: 【EF Core】优化后的模型