-
-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throw exception if accessing primary key on unflushed entity #2372
Comments
Not sure if I like this enough to make it default, will need to think about it a bit more (but it's definitely an interesting idea). I'd call this a breaking change for sure, and it should definitely be implemented in a way so a constrcutor calls will trigger that too, We could make this configurable, as I can imagine codebases where people check for the PK value explicitly - such code would now throw and require refactoring
Not really, initialized means that you have the data and not just PK, e.g. a naked reference is not initialized but it has a PK. You could check the PK value - but that can be also set without entity being flushed (e.g. UUID). To get around that, you'd have to also check if the identity map has such entity. The question is whether it makes sense to be so strict, e.g. you want to read the PK, the value is there, but we are not flushed. |
i started using
good point, though i'd imagine that only works if you send the instance to EM ( in which case, a base entity is helpful)? Or are you saying at bootstrap, you update the prototype for the entity class?
example use case?
yeah, that would be too strict, assuming the meta/entity is configured to persist that PK vs replace it with an auto-generated one, it would be safe to use the id downstream. the concern is just making sure we don't pass
right, and a new unflushed entity is technically initialized, so there would need to be some way to check if the primary key is to be generated and has not been provided |
It's fine to use them, it definitely makes sense with extensive usage of wrapped references as it can save a lot of code. What I meant is that I don't want to have a solution just for
I am fine with that as long as it would be optional. Not sure I understood the note about
Yes, during entity discovery the prototypes are patched. That is also the reason why entity discovery must always happen even in unit tests (while you can disable connection to database if you don't plan to use it).
Actually there is much easier way than using the identity map check I suggested before. You can simply check if
Well, exactly yours, isn't it? You want to know whether the PK is there. You are suggesting to throw when it's not there, people might be checking in |
i wouldn't say so, i don't think the following code should ever exist in most projects unless you are generating ids your self and want to check for the existence of it (which could be argued is the purpose of if(!entity.id){
// do x y z
} i can't think of an instance where a method would take an entity argument under the assumption that id would be undefined and alter execution behavior. add to the fact that i think most people are going to model their types like |
I am quite sure I saw such snippets either here in issues or on slack, and even if I haven't, I still consider this a breaking change - previously such code could exist and now the behaviour would change (of course only in case we enable this by default). But either way, I am not planning any more feature releases to v4, only bug fixes. |
another thought on this, what if we introduce a new type similar to IdentifierReference, like |
You don't have the right EM instance from inside new entities. I know you are using |
ah yes... only other thing that comes to mind is some type of flush callback system. eg: em.onFlush(entity, (entity) => {
em.create(other, {
metadata: {entity.id}
});
}); |
Having the patched prototype seems like the best way to me. |
@B4nan trying to figure out whether to build a solution or close and live with monkey patch. is it feasible to introduce a "wrapped" identifier option in the code base (excluding any need for flushing/having a reference to the EM) that would look like this: export class Entity {
@PrimaryKey({ type: BigIntType, wrapped: true })
private id = new GeneratedPrimaryKey<string>();
} |
I was recently fixing one issue with the promise.all and flushing resulting in flaky tests, and introduced async local storage context to the flush call to deal with it. We could use the same context, it literally tells you if you are inside the flush: https://github.com/mikro-orm/mikro-orm/blob/master/packages/core/src/unit-of-work/UnitOfWork.ts#L330 Haven't read the whole thread again, but I guess this should do it? We don't need to know the right EM, we just need to know if the current async context is inside flush handler, right? |
I think i'm ok with not worrying about flush yet, having to make downstream consumers async just to ensure an id exists seems iffy. and just throwing is at least a simpler v1 approach |
Is your feature request related to a problem? Please describe.
If a developer is unaware that an entity has been passed to them without an id, they may end up attempting to take action on it (eg: serialize to JSON) and never catch it, especially since there is no compile-time type checking to protect against this.
Describe the solution you'd like
When an entity is created through
manager.create()
, intercept calls to the primary key prior to flush and throw an exception, telling the user they need to flush first.Describe alternatives you've considered
Could potentially have a base entity class with
get id()
andset id()
which includes some check, though it isn't clear what the right approach is for determining "flushed",isInitialized
?This is what I am using now as a workaround:
The text was updated successfully, but these errors were encountered: