diff --git a/packages/database/src/index.ts b/packages/database/src/index.ts
index d223f0a60..905f5a80e 100644
--- a/packages/database/src/index.ts
+++ b/packages/database/src/index.ts
@@ -12,3 +12,4 @@ export * from './relation-repository/multiple-relation-repository';
 export { Model, ModelCtor } from 'sequelize';
 export * from './fields';
 export * from './update-associations';
+export * from './magic-attribute-model';
diff --git a/packages/database/src/magic-attribute-model.ts b/packages/database/src/magic-attribute-model.ts
new file mode 100644
index 000000000..dae165237
--- /dev/null
+++ b/packages/database/src/magic-attribute-model.ts
@@ -0,0 +1,46 @@
+import { Model } from 'sequelize';
+import { merge } from '@nocobase/utils';
+import _ from 'lodash';
+
+export class MagicAttributeModel extends Model {
+  set(key: any, value?: any, options?: any) {
+    if (typeof key === 'string') {
+      const [column] = key.split('.');
+      if ((this.constructor as any).hasAlias(column)) {
+        return super.set(key, value, options);
+      }
+      if ((this.constructor as any).rawAttributes[column]) {
+        return super.set(key, value, options);
+      }
+      if (_.isPlainObject(value)) {
+        const opts = super.get(`options`) || {};
+        return super.set(`options.${key}`, merge(opts?.[key], value), options);
+      }
+      return super.set(`options.${key}`, value, options);
+    } else {
+      Object.keys(key).forEach((k) => {
+        this.set(k, key[k], options);
+      });
+    }
+    return super.set(key, value, options);
+  }
+
+  get(key?: any, value?: any): any {
+    if (typeof key === 'string') {
+      const [column] = key.split('.');
+      if ((this.constructor as any).hasAlias(column)) {
+        return super.get(key, value);
+      }
+      if ((this.constructor as any).rawAttributes[column]) {
+        return super.get(key, value);
+      }
+      const options = super.get(`options`);
+      return _.get(options, key);
+    }
+    const data = super.get(key, value);
+    return {
+      ..._.omit(data, 'options'),
+      ...data.options,
+    };
+  }
+}
\ No newline at end of file