dotnetcore / FreeSql

🦄 .NET aot orm, C# orm, VB.NET orm, Mysql orm, Postgresql orm, SqlServer orm, Oracle orm, Sqlite orm, Firebird orm, 达梦 orm, 人大金仓 orm, 神通 orm, 翰高 orm, 南大通用 orm, 虚谷 orm, 国产 orm, Clickhouse orm, QuestDB orm, MsAccess orm.
http://freesql.net
MIT License
3.99k stars 842 forks source link

fsql.Aop.ConfigEntity 事件中,可以处理表名和索引名,但处理不了OraclePrimaryKeyNameAttribute设定的主键名称。 #1752

Open ensleep opened 2 months ago

ensleep commented 2 months ago

场景:

1、CodeFirst方式下,FreeSql提供了fsql.Aop.ConfigEntity事件,以修改实体与表名、索引名、主键名的对应关系。 2、由于Oracle对主键名称要求特殊,所以FreeSql提供了oracle专用的OraclePrimaryKeyNameAttribute特性来命名Oracle中对应的主键名称。

问题: 当我使用了fsql.Aop.ConfigEntity事件来修改实体与数据库对象之间的映射关系时,可以完成对表名、索引名称的修改,但是,却无法修改使用OraclePrimaryKeyNameAttribute所指定的Oracle的特定主键名,这应该是设计上的Bug。

影响: 1、当我编写一套自动部署数据库结构的程序时,一个用户空间下只能部署一个,如果想部署多个,即需要借助fsql.Aop.ConfigEntity事件来修改数据库对象的名称以防止多个部署互相冲突。但是,我无法在fsql.Aop.ConfigEntity事件中修改OraclePrimaryKeyNameAttribute的值,导致在Oracle中,表的主键重复,无法实现多个实例的部署。

问题描述及重现代码:

private static void FreeSql_Aop_ConfigEntity(object sender, FreeSql.Aop.ConfigEntityEventArgs e)
{
    if(!string.IsNullOrWhiteSpace(Services.GlobalConfigs.Table_Prefix))
    {

        // 修改索引
        var tp = Services.GlobalConfigs.Table_Prefix;
        var IndexAttrs = e.EntityType.GetCustomAttributes(typeof(IndexAttribute));
        foreach(IndexAttribute idx in IndexAttrs)
        {
            idx.Name = tp + idx.Name;
            e.ModifyIndexResult.Add(idx);
        }

        var OPkNameAttrs =(OraclePrimaryKeyNameAttribute) e.EntityType.GetCustomAttributes(typeof(OraclePrimaryKeyNameAttribute));
        if ( OPkNameAttrs != null)
        {
            // 无处修改 OPkNameAttrs中的Name
        }

        // 修改表名
        var TableAttr = (TableAttribute)e.EntityType.GetCustomAttributes(typeof(TableAttribute));
        if (TableAttr == null)
        {
            e.ModifyResult.OldName = tp + e.EntityType.GetType().Name;
        }
        else
        {
            if (!string.IsNullOrWhiteSpace(TableAttr.AsTable))
            {
                e.ModifyResult.AsTable = tp+ TableAttr.AsTable;
            }
            else if(!string.IsNullOrWhiteSpace(TableAttr.Name))
            {
                e.ModifyResult.Name = tp + TableAttr.Name;
            }
            else if (!string.IsNullOrWhiteSpace(TableAttr.OldName))
            {
                e.ModifyResult.OldName = tp + TableAttr.OldName;
            }
            else
            {
                e.ModifyResult.OldName = tp + e.EntityType.GetType().Name;
            }
        }
    }
}

数据库版本

所有版本

安装的Nuget包

<PackageReference Include="FreeSql" Version="3.2.685" />
<PackageReference Include="FreeSql.Extensions.BaseEntity" Version="3.2.685" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.16.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.7" />
<PackageReference Include="NuGet.Common" Version="6.9.1" />
<PackageReference Include="NuGet.Protocol" Version="6.9.1" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.100" />
<PackageReference Include="FreeSql.Provider.Oracle" Version="3.2.695" />

.net framework/. net core? 及具体版本

.net core 6.0

2881099 commented 2 months ago

OraclePrimaryKeyNameAttribute 是 oracle 的特殊处理。

如果不使用特性指定主键名,暂时先用 CodeFrst.GetDDLxxx() 方法获取迁移表结构的脚本,然后定位 replace 一下,再使用 Ado 执行,等有空了再处理 fluentapi 。