-
Notifications
You must be signed in to change notification settings - Fork 46
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
EF Core Support Extension #2 #513
Comments
I stumbled with this issue today. All my entities have a correct ID, but when EF needs to create a shadow property (for example, a hidden ID in an owned type), VoGen throws as the created struct is not initialized. This doesn't happen with class-based VO (as EF compares with null). Anyways, having both options (class/reference types) is not a bad idea, just in case. |
@SteveDunn Even if you end up implementing this or not, I think that in the same vein as |
Thanks for the suggestion @Aragas . I'm not that familiar with EFCore. In your example above, aside from the extension method, is that the entirety of what needs to be generated? As mentioned in #512 , we might need a new @CheloXL - Again, apologies, I not too familiar with EFCore. |
For the example above, I think this is the correct way:
This would be the same for both value and reference types. |
Regarding EF core: While you do not need a custom comparer for each converter you register, usually it is a good practice to have one. If you don't provide one, EF will use an internal one that basically uses Even if you fix the GetHashCode method, I'm not sure how that will work, as the Equals method between two uninitialized values returns false (and please note that for domain/business I think that's ok). But maybe for the EF value comparer, two uninitialized values should be equals. If you fix the GetHashCode, I could check if there are any differences using a custom value comparer/default (as right now I'm working on a project where the GetHashCode throws). |
Thanks @CheloXL , I'm doing a build now. I'm still wary of relaxing Of course, I'd like to make it possible for EFCore users to use it. It seems like the suggestions above will fix the hascode/comparison issue. If not, maybe |
@CheloXL you can use the converter example in the meantime from here #511 (comment) |
In my case EF Core is not the primary usecase for Vogen, so I believe GetHasCode is correct with it's check, since we are able to have a workaround by defining a custom converter and comparer |
feat: implement #513 EF Core add `EfCoreValueComparer'
@SteveDunn The problem with uninitalized values/ If you don't want to change the actual behavior, I propose two options:
What do you think? Is that ok for you? |
@SteveDunn I believe the right comparison would actually be |
Yes, that sounds reasonable @CheloXL . I'll add this to next next version |
This is now in the just-published beta package: https://www.nuget.org/packages/Vogen/3.0.23-beta.1 Would you both mind having a look to see if it looks OK? And maybe suggest some tests for the 'ConsumerTests' project? 🙏 |
Preliminary tests don't work. Ef is throwing a null reference exception inside a compiled lamba so I can't debug what's happening, but after reviwing some of the code, I suspect the problem is in the ValueComparer (If I don't register the ValueComparer along with the ValueConverter, I get the NotInitialized exception, but that's ok as that's the problem this tries to solve). The code I believe you should check if the VO is a struct or a class and add additional null checks where needed. In my code, some VO are structs and some are classes, that's why I'm getting one error or the other. |
Thanks @CheloXL - I'll get it to generate different code based on value/reference type |
Oh right, I forgot to add ReferenceEqual(value, null) to the check! |
Thanks @CheloXL - just doing a build a now. Would you be able to suggest any example tests or examples, e.g. something similar to what we already have here: https://github.com/SteveDunn/Vogen/blob/main/samples/Vogen.Examples/SerializationAndConversion/EFCore/EfCoreExamples.cs The next beta build should be there later today or tomorrow. |
@CheloXL - @Aragas The 2nd beta is there now on NuGet: https://www.nuget.org/packages/Vogen/3.0.23-beta.2 |
@SteveDunn It still doesn't work. It's missing a null check. I manually implemented a comparer for the VO that's currently failing. I'm attaching the code below. Please note that I had to expose public class InputDeviceIdEfCoreValueComparer : ValueComparer<InputDeviceId>
{
public InputDeviceIdEfCoreValueComparer() : base((left, right) => DoEquals(left, right), instance => DoGetHashCode(instance)) { }
private static bool DoEquals(InputDeviceId? left, InputDeviceId? right)
{
if (left is null)
{
return right is null;
}
if (right is null)
{
return false;
}
if (ReferenceEquals(left, right))
{
return true;
}
if (!left.IsInitialized && !right.IsInitialized)
{
return true;
}
return left.IsInitialized && right.IsInitialized && left.Value.Equals(right.Value);
}
private static int DoGetHashCode(InputDeviceId instance)
{
return instance.IsInitialized ? instance.GetHashCode() : 0;
}
} |
This addresses the following issue:
My suggestion as a fix is to introduce a custom
ValueComparer
, just like we have alreadyEfCoreValueConverter
And as an extension of #512, here's the new extension method:
The text was updated successfully, but these errors were encountered: