Skip to content
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

Added MongoSerializer and Mongo ObjectId backing type #62

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

marspion
Copy link

Hi, pull request is in draft but I would like to know your opinion about my idea for ObjectId support.

@andrewlock
Copy link
Owner

Hey, thanks! In principle, I'm certainly happy to support ObjectId 🙂 I wonder if this is the right way to handle it though 🤔 Would it be better to have ObjectId as a backing type, rather than just a serializer? Given you can't use any old string with objectid, the approach here looks like it could have some problems to me..

@marspion marspion changed the title Added MongoObjectIdSerializer for String and NullableString backingType Added MongoSerializer and Mongo ObjectId backing type Apr 4, 2022
@marspion
Copy link
Author

marspion commented Apr 4, 2022

Hi, I thought about your opinion and you have right. I added ObjectId backing type and modified MongoSerializer to work with all backing types instead of only string and nullable string. Please have a look after changes. If everything will be fine I will implement some unit and integration tests.

{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(MassTransit.NewId.FromGuid(new System.Guid(context.Reader.ReadString())));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to go through Guid here? You could use new NewId(context.Reader.ReadString()) I think 🙂 (similar for Serialize())

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have right :) I simplified it

@andrewlock
Copy link
Owner

Hi, I thought about your opinion and you have right. I added ObjectId backing type and modified MongoSerializer to work with all backing types instead of only string and nullable string. Please have a look after changes. If everything will be fine I will implement some unit and integration tests.

I think that looks much better @marspion, thanks! 🙂

@marspion
Copy link
Author

marspion commented May 9, 2022

Hello @andrewlock, I added some integration tests. Please verify it in your free time. Thanks!

Copy link
Owner

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks really good! I think there's a little inconsistency in the handling of null/"" values in the serializers, but otherwise I think this is pretty good to merge 🙂

public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
var result = reader.GetString();
return string.IsNullOrEmpty(result) ? TESTID.Empty : new TESTID(new MongoDB.Bson.ObjectId(result));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a discrepancy in the way you're handling null/empty string in these serializers. Some return null, some return TESTID.Empty, and some defer to the default handler

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ups, you have right. I will correct it.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @marspion, so it looks like you've made add the serializers return TESTID.Empty if the object can't be parsed? I'm not sure if that's the best behaviour. I'd expect a serializer to throw if it can't be parsed I think? Otherwise you could get unexpected behaviour?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @andrewlock

Sorry for my mistake but I mixed some cases and I noticed that serializers should not be responsible for it. Definitely it was bad idea to return TESTID.Empty. Now serializers assume that value should be valid otherwise they will throw.

@@ -19,23 +19,29 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0-*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0-*" />
<PackageReference Include="Mongo2Go" Version="3.1.1" />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL about Mongo2Go 🙂

Copy link
Author

@marspion marspion May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by TIL?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today I Learned 😄

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh so TIL about TIL 😃

@marspion
Copy link
Author

marspion commented May 9, 2022

@andrewlock Thank you for comment! I will correct code as soon as possible based on your review and also I will look up into errors returned from build pipeline.

@marspion
Copy link
Author

marspion commented May 9, 2022

@andrewlock I am not familiar with snapshots in tests. Do I have to change something before run StronglyTypedIds.Tests or everything should be green?

@andrewlock
Copy link
Owner

Thanks @marspion - snapshot testing is a way of confirming the output is what you expect. It's using this library, Verify. Dan Clarke has a good introduction to it here.

When you run the tests locally, the tests will all fail initially, as there aren't any "verified" files. The process to create them is generally:

  • Run the tests, generate the "received.txt" files. The tests will file
  • Take a look at the files-do they look like you would expect.
  • If you're happy, rename the received files to be "verified.txt" instead
  • Re-run the tests, they should now pass!

We currently generate every combination of serializer and attribute etc, so there's a lot of snapshots. You don't have to check every one, just make sure they look about right 🙂

P.S. You can also install the DiffEngineTray tool to make your life a little easier!

If you don't want to/can't get this working, I don't mind taking a look and pushing the snapshots for you to review instead

@marspion
Copy link
Author

Thank you @andrewlock for brief summary about test with snapshots! It is awesome!

As you recommended I used DiffEngineTray and I can agree that it is very helpful tool 🙂

To be honest I wasn't able to verify all snapshot files. I randomly verified some of them (different combinations).

I provided some changes to solve your CodeReview suggestions. Please take a look in your free time.

@andrewlock
Copy link
Owner

To be honest I wasn't able to verify all snapshot files. I randomly verified some of them (different combinations).

Yeah, there's so many combinations now that's about the best we can do 😆 I think it's going to be best to cut them down in a later PR.

It looks like there's a problem running Mongo2Go on Linux 🤔 Will take a look when I get a chance if you don't get to it first!

@marspion
Copy link
Author

I also will try to investigate what's going on with Mongo2Go on Linux

@marspion
Copy link
Author

marspion commented May 20, 2022

Hi @andrewlock I found some issue on Mongo2Go repository. Probably there is a problem with binaries search pattern on Linux OS (only some versions) but it has not resolved yet. As a workaround with access only to code I was able to override it.

Can you try to run build pipeline? I hope that will solve the problem.

Thanks!

Comment on lines 99 to 109
[Fact]
public void CanSerializeToNullable_WithNewtonsoftJsonProvider()
{
var entity = new EntityWithNullableId { Id = null };

var json = NewtonsoftJsonSerializer.SerializeObject(entity);
var deserialize = NewtonsoftJsonSerializer.DeserializeObject<EntityWithNullableId>(json);

Assert.NotNull(deserialize);
Assert.Equal(deserialize.Id, NewtonsoftJsonObjectIdId.Empty);
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should still be something we support shouldn't it? 🤔

@andrewlock
Copy link
Owner

Nice work on the Mongo2Go @marspion. I was just looking through the serializer changes, and I'm not entirely sure whether the serializers are completely consistent? Should we handle nulls explicitly or not worry about them? At the moment I'm concerned we might get null references when deserializing "invalid" values. I need to look through properly, but just to want make sure we're handling all the cases that we could hit 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants