[CSHARP-622] Add [MongoOldName("OldName")] attribute & updates to Linq provider Created: 31/Oct/12 Updated: 11/Mar/19 Resolved: 06/Apr/15 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | 1.6.1 |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | Tim Kellogg | Assignee: | Unassigned |
| Resolution: | Duplicate | Votes: | 1 |
| Labels: | linq, migration | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||
| Description |
|
One common use-case for attempting migrations is for things like renaming fields. If you rename a property from `OldName` to `NewName`, the existing documents won't have been updated so `NewName` will typically be null. The defensive coding argument is to use [MongoExtraElements] attribute to fill a dictionary and update your CLR object accordingly. The issue with the defensive coding strategy is that you can't query against `NewName` until the object has been updated & saved. Most documents may take a while before they're upgraded, and some may never be upgraded. In the meantime, we would have to sprinkle all of our queries with `Query.OR(Query.EQ("NewName", "foo"), Query.EQ("OldName", "foo"))`. I propose that we solve this querying issue by updating the Linq driver to automatically do (x.NewName == "foo" || x.OldName == "foo") whenever a field has been renamed. To rename a field, I propose a [MongoOldName(<old-name>)] attribute. I believe that this case of renaming a field is very common. Due to the nature of Mongo, I also think it's best to implement this at the driver level. |
| Comments |
| Comment by Tim Kellogg [ 20/Dec/12 ] |
|
I did some thinking about a more complete implementation than I suggested here. I wrote a demonstration implementation of the sort of changes I’d like to see in the driver. Aside from those changes, I’d like to see migrations implemented outside the core driver DLL using those hooks. The migration-spike branch of my fork is at https://github.com/tkellogg/mongo-csharp-driver/tree/migration-spike. The main type you should be paying attention to is IBsonSerializationEventHook (https://github.com/tkellogg/mongo-csharp-driver/blob/migration-spike/Bson/Serialization/IBsonSerializationEventHook.cs) and where it ties in to BsonClassMapSerializer. I still haven’t written any interfaces for processing queries for migrations. I just wanted to see if it was plausible. In our own (proprietary) code I implemented some migrations for specific purposes (rename a specific property, change type of a specific property, nothing generic). I can’t share that code, but it was only enough to prove the concept anyway. I’m writing all this to see if you like the direction. I think we should discuss this in an open forum before investing too much effort. I like the idea of keeping the driver changes as small as possible and starting an external project for migrations, so they can be optional. I imagine that we won’t get the API right the first time, so this is an incremental approach that leaves room for alternative migration APIs. |
| Comment by Tim Kellogg [ 02/Nov/12 ] |
|
Thinking about this, it doesn't entirely solve the upgrade problem for field renames. For instance, consider a cloud with two web servers (A & B). After you upgrade server A to rename "OldName" to "NewName", queries from server B will be invalid until it's also upgraded; because it's queries will only know to look at "OldName". With the above solution, if I wanted assurances that I didn't have any invalid states I would have to do a complicated switcheroo: 1. pre-plan the rename by placing an [MongoOldName("NewName")] attribute This is a complicated way to make these guarantees. One route to consider is adding configuration file support for this specific scenario (since config files don't require a recompile and often no restart). Regardless, I hope there's an even better answer that can be more automated. |
| Comment by Craig Wilson [ 31/Oct/12 ] |
|
I'm not sure it's a lot of work, just we need to make sure it's done correctly, so definitely would like to discuss before going off and doing it. I think it's just a matter of putting the hooks in the right places, so likely some rearchitecture would be needed. Thanks for volunteering and let us know if this is something you want to tackle and when. We'll make sure we get on a phone call or something to discuss when you are ready. |
| Comment by Tim Kellogg [ 31/Oct/12 ] |
|
If the issue is the amount of work, I think I might be able to get time to do this at work. I would just want more discussion around it before I invested time. |
| Comment by Craig Wilson [ 31/Oct/12 ] |
|
Good suggestion and thanks for creating a Jira for this. We have discussed this internally but haven't pulled the trigger yet. |