Originally created by @dwirandytlvk on GitHub (Jan 5, 2023).
HI @JohnEstropia
i would like to ask about lightweight migration in CoreStore
i watch at WWDC video https://developer.apple.com/videos/play/wwdc2022/10120/ that we can do lightweight migration without creating new model version.
Does CoreStore has support to do that?
Since i have many model/table that will be a tedious process to duplicate previous model into new version and make adjustment in new version model
thank you in advance 🙏
Originally created by @dwirandytlvk on GitHub (Jan 5, 2023).
HI @JohnEstropia
i would like to ask about lightweight migration in `CoreStore`
i watch at WWDC video https://developer.apple.com/videos/play/wwdc2022/10120/ that we can do lightweight migration without creating new model version.
Does `CoreStore` has support to do that?
Since i have many model/table that will be a tedious process to duplicate previous model into new version and make adjustment in new version model
thank you in advance 🙏
adam
added the question label 2025-12-29 15:30:59 +01:00
I think you misunderstood. Lightweight migrations allow for migrations between two model versions, without creating a Mapping Model. You still need to keep the models from your past versions.
@JohnEstropia commented on GitHub (Jan 5, 2023):
I think you misunderstood. Lightweight migrations allow for migrations between two model versions, without creating a *Mapping Model*. You still need to keep the models from your past versions.
With that in mind, CoreStore does support lightweight migrations. See https://github.com/JohnEstropia/CoreStore#migrations
enum V1 {
class User: CoreStoreObject {
@Field.Relationship("profile", inverse: \.$user, deleteRule: .cascade)
var profile: UserProfile?
@Field.Relationship("authentication", inverse: \.$user, deleteRule: .cascade)
var authentication: UserAuthentication?
}
class UserAuthentication: CoreStoreObject {
@Field.Stored("_loginMethod")
var _loginMethod: String? = nil
@Field.Stored("loginId")
var loginId: String? = nil
@Field.Stored("profileId")
var profileId: String? = nil
@Field.Stored("lastLoginTimetamp")
var lastLoginTimestamp: Int = 0
@Field.Stored("createdTimestamp")
var createdTimestamp: Int = 0
// Foreign Key Relationship
@Field.Relationship("user")
var user: User?
}
class UserProfile: CoreStoreObject {
@Field.Stored("name")
var name: String? = nil
@Field.Coded("phoneNumbers", coder: FieldCoders.Json.self)
var phoneNumbers: [String] = []
@Field.Relationship("emails", inverse: \.$userProfile, deleteRule: .cascade)
var emails: [UserEmail]
@Field.Stored("")
var photoUrl: String? = nil
// Foreign Key Relationship
@Field.Relationship("user")
var user: User?
}
class UserEmail: CoreStoreObject {
@Field.Stored("email")
var email: String = ""
// Foreign Key Relationship
@Field.Relationship("userProfile")
var userProfile: UserProfile?
}
}
and after i publish my app, i want to update my published app and add 2 column in UserAuthentication which isCorporateUser and isVerified, so i have to copy my previous CoreStoreObject from v1, into enum v2 and add 2 column into UserAuthentication
enum V2 {
class User: CoreStoreObject, ImportableObject {
typealias ImportSource = [String: Any]
@Field.Relationship("profile", inverse: \.$user, deleteRule: .cascade)
var profile: UserProfile?
@Field.Relationship("authentication", inverse: \.$user, deleteRule: .cascade)
var authentication: UserAuthentication?
func didInsert(from source: [String : Any], in transaction: CoreStore.BaseDataTransaction) throws {
let profileJson = source["profile"] as? UserProfile.ImportSource ?? [:]
profile = try transaction.importObject(Into<UserProfile>(), source: profileJson)
let authenticationJson = source["authentication"] as? UserProfile.ImportSource ?? [:]
authentication = try transaction.importObject(Into<UserAuthentication>(), source: authenticationJson)
}
}
class UserAuthentication: CoreStoreObject, ImportableObject {
typealias ImportSource = [String: Any]
@Field.Stored("_loginMethod")
var _loginMethod: String? = nil
@Field.Stored("loginId")
var loginId: String? = nil
@Field.Stored("profileId")
var profileId: String? = nil
@Field.Stored("lastLoginTimetamp")
var lastLoginTimestamp: Int = 0
@Field.Stored("createdTimestamp")
var createdTimestamp: Int = 0
// Foreign Key Relationship
@Field.Relationship("user")
var user: User?
// Additional Field
@Field.Stored("isCorporateUser")
var isCorporateUser: Bool = false
@Field.Stored("isVerified")
var isVerified: Bool = false
func didInsert(from source: [String : Any], in transaction: CoreStore.BaseDataTransaction) throws {
_loginMethod = source["_loginMethod"] as? String ?? ""
loginId = source["loginId"] as? String ?? ""
profileId = source["profileId"] as? String ?? ""
lastLoginTimestamp = source["lastLoginTimestamp"] as? Int ?? 0
createdTimestamp = source["createdTimestamp"] as? Int ?? 0
}
}
class UserProfile: CoreStoreObject, ImportableObject {
typealias ImportSource = [String: Any]
@Field.Stored("name")
var name: String? = nil
@Field.Coded("phoneNumbers", coder: FieldCoders.Json.self)
var phoneNumbers: [String] = []
@Field.Relationship("emails", inverse: \.$userProfile, deleteRule: .cascade)
var emails: [UserEmail]
@Field.Stored("photoUrl")
var photoUrl: String? = nil
// Foreign Key Relationship
@Field.Relationship("user")
var user: User?
func didInsert(from source: [String : Any], in transaction: CoreStore.BaseDataTransaction) throws {
name = source["name"] as? String ?? ""
phoneNumbers = source["phoneNumbers"] as? [String] ?? []
photoUrl = source["photoUrl"] as? String ?? ""
let emailJson: [UserEmail.ImportSource] = source["emails"] as? [UserEmail.ImportSource] ?? []
emails = try transaction.importObjects(Into<UserEmail>(), sourceArray: emailJson)
}
}
class UserEmail: CoreStoreObject, ImportableObject {
typealias ImportSource = [String: Any]
@Field.Stored("email")
var email: String = ""
@Field.Stored("domain")
var domain: String = ""
// Foreign Key Relationship
@Field.Relationship("userProfile")
var userProfile: UserProfile?
func didInsert(from source: [String : Any], in transaction: CoreStore.BaseDataTransaction) throws {
email = source["email"] as? String ?? ""
}
}
}
No, it won't be. Core Data needs to know the old model for it to determine if any migrations, including lightweight ones, are needed in the first place.
To save you some maintenance work when adding new versions, I recommend using typealiases for your model classes, as shown in some examples in the README:
This way, you'd only need to refer to V1 or V2 in your migration setup code, and your app can use the aliased names forever.
@JohnEstropia commented on GitHub (Jan 5, 2023):
> i'm wondering is it possible
No, it won't be. Core Data needs to know the old model for it to determine if any migrations, including lightweight ones, are needed in the first place.
To save you some maintenance work when adding new versions, I recommend using `typealias`es for your model classes, as shown in some examples in the README:
<img width="854" alt="Screen Shot 2023-01-05 at 18 56 05" src="https://user-images.githubusercontent.com/3029684/210752553-5187f624-469b-4f45-8959-351199d640dc.png">
This way, you'd only need to refer to `V1` or `V2` in your migration setup code, and your app can use the aliased names forever.
ah i see okay, thanks john @JohnEstropia
May i know what is your suggestion if i have more than 50 CoreStoreObject that separated in several modules how to manage each object based on version?
For example i have 10 CoreStoreObject in Booking Module, 20 CoreStoreObject in Flight Module and 30 CoreStoreObject in Hotel Module each CoreStoreObject has relationship each other, so i can not be split into multiple database
@dwirandytlvk commented on GitHub (Jan 10, 2023):
ah i see okay, thanks john @JohnEstropia
May i know what is your suggestion if i have more than 50 CoreStoreObject that separated in several modules how to manage each object based on version?
For example i have 10 CoreStoreObject in `Booking Module`, 20 CoreStoreObject in `Flight Module` and 30 CoreStoreObject in `Hotel Module` each CoreStoreObject has relationship each other, so i can not be split into multiple database
@dwirandytlvk You're more familiar with your object relationships so this would be up to you, but you have many options:
let the module that sets up your DataStack depend on all modules that contain your objects
separate all ORM-related code to its own module
inject the CoreStoreObject subclasses dynamically during DataStack setup. CoreStoreSchema doesn't need static typing, just the Entity<T> instance passed as DynamicEntity:
@JohnEstropia commented on GitHub (Jan 12, 2023):
@dwirandytlvk You're more familiar with your object relationships so this would be up to you, but you have many options:
- let the module that sets up your `DataStack` depend on all modules that contain your objects
- separate all ORM-related code to its own module
- inject the `CoreStoreObject` subclasses dynamically during `DataStack` setup. `CoreStoreSchema` doesn't need static typing, just the `Entity<T>` instance passed as `DynamicEntity`: <img width="784" alt="Screen Shot 2023-01-12 at 11 24 36" src="https://user-images.githubusercontent.com/3029684/211961072-5378c696-ead1-4736-aefc-ff4483195377.png">
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @dwirandytlvk on GitHub (Jan 5, 2023).
HI @JohnEstropia
i would like to ask about lightweight migration in
CoreStorei watch at WWDC video https://developer.apple.com/videos/play/wwdc2022/10120/ that we can do lightweight migration without creating new model version.
Does
CoreStorehas support to do that?Since i have many model/table that will be a tedious process to duplicate previous model into new version and make adjustment in new version model
thank you in advance 🙏
@JohnEstropia commented on GitHub (Jan 5, 2023):
I think you misunderstood. Lightweight migrations allow for migrations between two model versions, without creating a Mapping Model. You still need to keep the models from your past versions.
With that in mind, CoreStore does support lightweight migrations. See https://github.com/JohnEstropia/CoreStore#migrations
@dwirandytlvk commented on GitHub (Jan 5, 2023):
Perhaps i will explain my case study
I have three table
and after i publish my app, i want to update my published app and add 2 column in
UserAuthenticationwhichisCorporateUserandisVerified, so i have to copy my previous CoreStoreObject from v1, into enum v2 and add 2 column intoUserAuthenticationSo my DataStack will be like this
i'm wondering is it possible, to not create
V2and just add new column intoUserAuthenticationinV1?@JohnEstropia commented on GitHub (Jan 5, 2023):
No, it won't be. Core Data needs to know the old model for it to determine if any migrations, including lightweight ones, are needed in the first place.
To save you some maintenance work when adding new versions, I recommend using

typealiases for your model classes, as shown in some examples in the README:This way, you'd only need to refer to
V1orV2in your migration setup code, and your app can use the aliased names forever.@dwirandytlvk commented on GitHub (Jan 10, 2023):
ah i see okay, thanks john @JohnEstropia
May i know what is your suggestion if i have more than 50 CoreStoreObject that separated in several modules how to manage each object based on version?
For example i have 10 CoreStoreObject in
Booking Module, 20 CoreStoreObject inFlight Moduleand 30 CoreStoreObject inHotel Moduleeach CoreStoreObject has relationship each other, so i can not be split into multiple database@JohnEstropia commented on GitHub (Jan 12, 2023):
@dwirandytlvk You're more familiar with your object relationships so this would be up to you, but you have many options:
DataStackdepend on all modules that contain your objectsCoreStoreObjectsubclasses dynamically duringDataStacksetup.CoreStoreSchemadoesn't need static typing, just theEntity<T>instance passed asDynamicEntity: