分享你们的自定义特性实现代码 返回

IT新闻 老数据
11 13618

1、描述你的自定义特性的功能

      比如是兼容EF的特性又或者是统一处理 string类型不能是自增列这一功能等

2、禁止水贴 

热忱回答11

  • wosperry wosperry VIP0
    2021/12/31

            /// <summary>

            /// 兼容特性,不引用Sugar命名空间

            /// </summary>

            private static ConfigureExternalServices ConfigureMigrateAttributeInfo()

            {

                ConfigureExternalServices externalServices = new ConfigureExternalServices();


                // 配置实体

                externalServices.EntityNameService = (type, tableInfo) =>

                {

                    var tableAttr = type.GetCustomAttribute<TableAttribute>(false);

                    if (tableAttr != null)

                    {

                        tableInfo.DbTableName = tableAttr.Name;

                    }

                };

                // 配置字段

                externalServices.EntityService=(propInfo, columnInfo) =>

                {

                    var keyAttr = propInfo.GetCustomAttribute<KeyAttribute>();

                    if (keyAttr is not null)

                        columnInfo.IsPrimarykey = true;


                    var columnAttr = propInfo.GetCustomAttribute<ColumnAttribute>();

                    if (columnAttr is not null)

                        columnInfo.DbColumnName =columnAttr.Name;


                    var commentAttr = propInfo.GetCustomAttribute<CommentAttribute>();

                    if (commentAttr is not null)

                        columnInfo.ColumnDescription =commentAttr.Comment;


                    var maxlengthAttr = propInfo.GetCustomAttribute<MaxLengthAttribute>();

                    if (maxlengthAttr is not null)

                        columnInfo.Length = maxlengthAttr.Length;


                    var stringlengthAttr = propInfo.GetCustomAttribute<StringLengthAttribute>();

                    if (stringlengthAttr is not null)

                        columnInfo.Length = stringlengthAttr.MaximumLength;


                    var notmappedAttr = propInfo.GetCustomAttribute<NotMappedAttribute>();

                    if (notmappedAttr is not null) columnInfo.IsIgnore = true;

                };

                return externalServices;

            }


    0 回复
  • 请问使用仓储模式时,怎么使用ConfigureExternalServices代码指定实体列的属性呢。


    我的注入代码



                //注册SqlSugar

                services.AddSqlSugar(new IocConfig()

                {

                    ConnectionString = configuration.GetSection("MainDb/ConnectionString").Value,

                    DbType = dbType,

                    IsAutoCloseConnection = true

                });


                SugarIocServices.ConfigurationSugar(db => {

                });

    我的仓储类代码


        public abstract class BaseRepository<TEntity,TSugarEntity> : SimpleClient<TEntity>,IBaseRepository<TEntity> where TEntity : class, new()

        {

            private readonly IMapper _mapper;


            public BaseRepository(ISqlSugarClient? context = null, IMapper mapper=null) : base(context)

            {

                base.Context = DbScoped.SugarScope;

            }

         }


    0 回复
  • fate sta fate sta VIP0
    2022/7/26

    @陪一个人走走

        SugarIocServices.ConfigurationSugar(db => {

                     db.ConfigureExternalServices =new xxxx

                });


    0 回复
  • @fate sta:可是这样写会提示ConfigureExternalServices 属性不存在。是不是没有引用什么类库造成的?

    QQ截图20220726170701.png

    0 回复
  • fate sta fate sta VIP0
    2022/7/26

    @陪一个人走走:db.CurrenctConfig.xxx

    0 回复
  • @fate sta:可以了,谢谢!!

    0 回复
  • 疋疋 疋疋 VIP0
    2023/3/14

    仅供参考:EntityService映射的转化方法,理论上无需引用 Sqlsugar,

            /// <summary>
            /// 实体生成服务控制器
            /// </summary>
            /// <param name="property"></param>
            /// <param name="column"></param>
            /// <exception cref="Exception"></exception>
            void EntityServiceHandler(PropertyInfo property, EntityColumnInfo column)
            {
                var attributes = property.GetCustomAttributes(true);
    
                #region System.ComponentModel.DataAnnotations.Schema
                // 判断是否存在Key 特性,如果存在,就标记字段为主键
                if (attributes.Any(a => a is KeyAttribute))
                {
                    column.IsPrimarykey = true;
                }
                else
                {
                    column.IsNullable = true;// 除主键字段以外,所以字段默认都为可空类型
                }
                // 判断是否有标记字段的生成模式
                if (attributes.FirstOrDefault(f => f is DatabaseGeneratedAttribute) is DatabaseGeneratedAttribute attrDatabaseGenerated)
                {
                    switch (attrDatabaseGenerated.DatabaseGeneratedOption)
                    {
                        case DatabaseGeneratedOption.None:
                            column.IsIgnore = true;// 貌似是忽略不生成
                            break;
                        case DatabaseGeneratedOption.Identity:
                            column.IsIdentity = true;
    
                            if (typeof(int) == column.UnderType)
                            {
                                if (column.OracleSequenceName.IsNullOrEmpty())
                                {
                                    column.OracleSequenceName = column.DbColumnName;// Oracle 自增列时 时需要设置此参数
                                }
                            }
                            break;
                        case DatabaseGeneratedOption.Computed:// 貌似是数据库的计算属性
                            column.IsOnlyIgnoreInsert = true;
                            column.IsOnlyIgnoreUpdate = true;
                            break;
                        default:
                            break;
                    }
                }
                // 直接忽略该字段
                if (attributes.Any(a => a is NotMappedAttribute))
                {
                    column.IsIgnore = true;
                }
                // 字段列设置
                if (attributes.FirstOrDefault(f => f is ColumnAttribute) is ColumnAttribute attrColumn)
                {
                    column.DbColumnName = attrColumn.Name;
                    column.DataType = attrColumn.TypeName;
                    //attrColumn.Order
                }
                // 当A和B 是一对多的关系,并且A中有多个B类型数据,通过此数据将B中每个集合字段对应上A的成员
                if (attributes.FirstOrDefault(f => f is InversePropertyAttribute) is InversePropertyAttribute attrInverseProperty)
                {
                    column.IsIgnore = true;
                    Navigate navigate;
    
                    // 此处判断当前属性是否为 List 的集合类型,如果是集合类型,则可能是一对多,也可能是多对多
                    // 判断构造函数是否 为泛型 ,继承了泛型集合 ,同时泛型类型存在值
                    if (column.UnderType.IsConstructedGenericType && column.UnderType.GenericTypeArguments.Length > 0)
                    {
                        // 获取泛型的类型
                        var definType = column.UnderType.GenericTypeArguments[0];
                        // 获取类型下的属性
                        var propInfo = definType.GetProperty(attrInverseProperty.Property, BindingFlags.Public | BindingFlags.Instance);
                        if (propInfo == null)
                        {
                            throw new Exception("没有找到对应类型上的字段");
                        }
                        //对方字段的类型
                        navigate = new Navigate(NavigateType.OneToMany, attrInverseProperty.Property);
    
                    }
                    else
                    {
                        // 剩下情况则为一对一
                        navigate = new Navigate(NavigateType.OneToOne, attrInverseProperty.Property);
                    }
    
                    // 主表ID
                    column.Navigat = navigate;
                }
                if (attributes.FirstOrDefault(f => f is ForeignKeyAttribute) is ForeignKeyAttribute attrForeignKey)
                {
                    //column.IsIgnore = true;
                    // 需要检查本身数据类型
                    //column.Navigat.NavigatType = NavigateType.OneToMany;
                    //column.Navigat.MappingAId = attrInverseProperty.Property;
                }
                #endregion
    
                #region System.ComponentModel.DataAnnotations
                // 是否必填字段
                //if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                //{
                //    column.IsNullable = true;
                //}
                if (attributes.FirstOrDefault(f => f is RequiredAttribute) is RequiredAttribute attrRequired)
                {
                    column.IsNullable = false;
                }
                // 字段长度
                if (attributes.FirstOrDefault(f => f is StringLengthAttribute) is StringLengthAttribute attrStringLength)
                {
                    column.Length = attrStringLength.MaximumLength;
                }
                // 字段长度
                if (attributes.FirstOrDefault(f => f is MaxLengthAttribute) is MaxLengthAttribute attrMaxLength)
                {
                    column.Length = attrMaxLength.Length;
                }
                // 列描述信息
                if (attributes.FirstOrDefault(f => f is DisplayAttribute) is DisplayAttribute attrDiaplay)
                {
                    column.ColumnDescription = attrDiaplay.Name;
                }
                // 标识版本字段,时间戳字段
                if (attributes.FirstOrDefault(f => f is TimestampAttribute) is TimestampAttribute attrTimestamp)
                {
                    column.IsEnableUpdateVersionValidation = true; // 启用版本控制
    
                    //column.IsOnlyIgnoreInsert = true;// 忽略插入
                    //column.IsOnlyIgnoreUpdate = true;// 忽略更新
                    static bool checkColumnType(Type typ)
                    {
                        if (typ == typeof(Guid)
                            || typ == typeof(long)
                            || typ == typeof(string)
                            || typ == typeof(DateTime))
                            return true;
                        else
                            return false;
                    }
                    if (!checkColumnType(column.UnderType))
                    {
                        throw new Exception("时间戳字段目前允许使用的数据类型为:Guid、long、string、DateTime");
                    }
    
    
                }
                // 忽略
                //if (attributes.FirstOrDefault(f => f is ConcurrencyCheckAttribute) is ConcurrencyCheckAttribute attrConcurrencyCheck)
                //{
                //}
                //if (attributes.FirstOrDefault(f => f is DisplayAttribute) is ColumnAttribute attrColumn)
                //{
    
                //}
    
                #endregion
    
    
                #region 自定义的特性
                if (attributes.FirstOrDefault(f => f is JsonAttribute) is JsonAttribute jsonAttribute)
                {
                    column.IsJson = true;
                    column.DataType = "varchar";
                }
                #endregion
    
    
                //! 如果字符串字段没有给定过长度,则默认长度为 50
                if (column.Length == 0 && column.UnderType == typeof(string))
                {
                    column.Length = 50;
                }
            }


    0 回复
  • ☑ YHS ☑ YHS VIP0
    2023/3/28
    • 1.DatabaseGeneratedOption.None
      自己输入值,不用数据库生成的

    • 2.NotMapped 特性

    • 不映射实体的属性到数据库表格中的列。

    • 3.DatabaseGeneratedOption.Computed
      在插入或更新的时候来设置值,需要我们自己计算的值  例如"GETDATE()"

    • 4.TimeStamp

    • 一个实体类中只可有一个类型为TimeStamp,用于并发检测
      [TimeStamp],SQLServer中是这样,但是没有装,我也没试。在MySql中,此法无效。需要加入ConCurrencyCheck

      concurrencycheck与timestamp区别
      concurrencycheck可用于多个属性的任意数据类型的检测
      timestamp只可用于一个byte[]类型属性的检测,一个实体中只可有一个此类型


    0 回复
  • ☑ YHS ☑ YHS VIP0
    2023/3/28

    @疋疋:有几个问题

    0 回复
  • @疋疋:大神,这个怎么使用呢?放在什么地方呢

    0 回复
  • 漫步 漫步 VIP0
    2024/11/4

    使用自定义类型实现同一套代码兼容不通数据库的空间字段的写入和查询


       ConfigureExternalServices = new ConfigureExternalServices()

            {

                SqlFuncServices = expMethods,

                EntityService = (property, column) =>

                {

                    var attributes = property.GetCustomAttributes(true);

                    if (attributes.Any(it => it is CustomeGeomemoryAttribute))

                    {

                        switch (dbtype)

                        {

                            case DbType.PostgreSQL:

                            case DbType.HG:

                                column.UpdateSql = "st_geomfromewkt('{0}')";

                                column.InsertSql = "st_geomfromewkt('{0}')";

                                column.QuerySql = $"ST_AsText({column.DbColumnName})";

                                break;

                            case DbType.Dm:

                                column.UpdateSql = "dmgeo2.st_geomfromtext('{0}',4326)";

                                column.InsertSql = "dmgeo2.st_geomfromtext('{0}',4326)";

                                column.QuerySql = $"dmgeo2.ST_AsText({column.DbColumnName})";

                                break;

                            default:

                                break;

                        }                    

                    }

                }

            }


    0 回复