xianhc / apevolo-api

.Net 8 、SqlSugar ORM、Vue 2.X、RBAC、前后端分离的开箱则用的企业级中后台权限管理系统
https://www.apevolo.com
Apache License 2.0
809 stars 74 forks source link

FxAssemblies和EntityAssemblys硬编码可以去掉 #8

Closed huster-songtao closed 2 years ago

huster-songtao commented 2 years ago
    static readonly List<string> FxAssemblies = new List<string>
        { "ApeVolo.Repository", "ApeVolo.Business", "ApeVolo.IBusiness", "ApeVolo.Entity" };

    static readonly List<string> EntityAssemblys = new List<string> { "ApeVolo.Entity" };

这些代码硬编码,不够灵活了 参考文章:https://dotnetcoretutorials.com/2020/07/03/getting-assemblies-is-harder-than-you-think-in-c/

        var allTypes = new List<Type>();
        var assemblyNames = Assembly.GetEntryAssembly()?.GetReferencedAssemblies().Where(x => x.Name != null && x.Name.StartsWith("ApeVolo.")); // .Select(r => r.FullName)
        assemblyNames?.Select(r => Assembly.Load(r)).ToList().ForEach(a => allTypes.AddRange(a.GetTypes()));
        FxAllTypes = allTypes;

        // 实体
        List<Type> entityTypes = new List<Type>();
        Assembly.GetEntryAssembly()?.GetReferencedAssemblies()
            .Where(x => x.Name != null && x.Name.Contains(".Entity"))
            .Select(x => Assembly.Load(x)).ToList()
            .ForEach(e => { entityTypes.AddRange(e.GetTypes()); });
        //var entityAssemblys = EntityAssemblys.Select(x => Assembly.Load(x)).ToList();
        //entityAssemblys.ForEach(entityAssembly => { entityTypes.AddRange(entityAssembly.GetTypes()); });
        EntityTypes = entityTypes;

初始化数据库.... 初始化数据库成功。

初始化数据表.... Entity:QuartzNet-->Table:sys_quartz_job-->Desc:作业调度-->创建完成! Entity:QuartzNetLog-->Table:sys_quartz_job_log-->Desc:作业调度执行日志-->创建完成! Entity:AuditLog-->Table:sys_audit_log-->Desc:审计日志表-->创建完成! Entity:Log-->Table:sys_log-->Desc:系统日志表-->创建完成! Entity:EmailAccount-->Table:sys_email_account-->Desc:邮件账户表-->创建完成! Entity:MessageTemplate-->Table:sys_email_message_template-->Desc:邮件消息模板-->创建完成! Entity:QueuedEmail-->Table:sys_queued_email-->Desc:邮件队列-->创建完成! Entity:Dict-->Table:sys_dict-->Desc:字典表-->创建完成! Entity:DictDetail-->Table:sys_dict_detail-->Desc:字典详细表-->创建完成! Entity:AppSecret-->Table:sys_app_secret-->Desc:三方应用秘钥表-->创建完成! Entity:Department-->Table:sys_department-->Desc:部门表-->创建完成! Entity:FileRecord-->Table:sys_file_record-->Desc:文件记录表-->创建完成! Entity:Job-->Table:sys_job-->Desc:岗位表-->创建完成! Entity:Menu-->Table:sys_menu-->Desc:系统菜单表-->创建完成! Entity:Role-->Table:sys_role-->Desc:角色表-->创建完成! Entity:RoleMenu-->Table:sys_roles_menus-->Desc:角色与菜单关联表-->创建完成! Entity:RolesDepartments-->Table:sys_roles_depts-->Desc:角色部门-->创建完成! Entity:Setting-->Table:sys_setting-->Desc:系统设置表-->创建完成! Entity:TestApeVolo-->Table:test_apevolo-->Desc:测试表-->创建完成! Entity:User-->Table:sys_user-->Desc:系统用户表-->创建完成! Entity:UserJobs-->Table:sys_users_jobs-->Desc:用户岗位关联表-->创建完成! Entity:UserRoles-->Table:sys_users_roles-->Desc:用户角色关联表-->创建完成! 初始化数据表成功!

测试没有问题。

xianhc commented 2 years ago

感谢你的提议,但是使用全局获取的方式也并非最合理,因为我可能不停的增加项目,而那些项目我并不希望注入

huster-songtao commented 2 years ago

硬编码不够灵活了

huster-songtao commented 2 years ago

说起硬编码

   /// <summary>
    /// 查询单个对象
    /// </summary>
    /// <param name="id">列值</param>
    /// <param name="columnName">列名 默认ID</param>
    /// <returns>实体对象</returns>
    public async Task<TEntity> QuerySingleAsync(object id, string columnName = "id")
    {
        if (id.IsNull())
        {
            throw new BadRequestException("请传入id");
        }

        var conModels = new List<IConditionalModel>
        {
            new ConditionalModel
            {
                FieldName = columnName, ConditionalType = ConditionalType.Equal, FieldValue = id.ToString()
            },
            new ConditionalModel
            {
                FieldName = "is_deleted", ConditionalType = ConditionalType.Equal, FieldValue = "0"
            }
        };
        return await _db.Queryable<TEntity>().Where(conModels).SingleAsync();
        // 这种方式不适合软删除模式
        // return await _db.Queryable<TEntity>().InSingleAsync(id);
    }

这里的"id"就是属于硬编码

    /// <summary>
    /// 查询单个对象
    /// </summary>
    /// <param name="fieldValue">列值</param>
    /// <param name="fieldName">列名 默认ID</param>
    /// <returns>实体对象</returns>
    public async Task<TEntity> QuerySingleAsync(object fieldValue, string fieldName = "id")
    {
        if (fieldValue.IsNull())
        {
            throw new BadRequestException("请传入id");
        }

        var conModels = new List<IConditionalModel>
        {
            new ConditionalModel
            {
                FieldName = fieldName, ConditionalType = ConditionalType.Equal, FieldValue = fieldValue.ToString()
            },
            new ConditionalModel
            {
                FieldName = "is_deleted", ConditionalType = ConditionalType.Equal, FieldValue = "0"
            }
        };
        return await _db.Queryable<TEntity>().Where(conModels).SingleAsync();
        // 这种方式不适合软删除模式
        // return await _db.Queryable<TEntity>().InSingleAsync(id);
    }

改成这样,从方法定义上,就通用点了

实体基类也存在硬编码的情况,默认使用long了,有很多场合用int,而不是long

public abstract class Entity<TId>
{
    public virtual TId Id { get; set; }

    protected sealed override IEnumerable<object> Equals()
    {
        yield return Id;
    }
}

我推荐用这样的基类,这样可以指定Id用int还是用long

推荐自增主键使用int unsigned类型,但不建议使用bigint。

有符号int最大可以支持到约22亿,远远大于我们的需求和MySQL单表所能支持的性能上限。对于OLTP应用来说,单表的规模一般要保持在千万级别,不会达到22亿上限。如果要加大预留量,可以把主键改为改为无符号int,上限为42亿,这个预留量已经是非常的充足了。

long long是64bit存储的,而int只有32bit。使用bigint,会占用更大的磁盘和内存空间,内存空间毕竟有限,无效的占用会导致更多的数据换入换出,额外增加了IO的压力,对性能是不利的。