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

Copy() Method and EF Core's ValueComparer #598

Open
Aragas opened this issue May 21, 2024 · 4 comments
Open

Copy() Method and EF Core's ValueComparer #598

Aragas opened this issue May 21, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@Aragas
Copy link

Aragas commented May 21, 2024

Describe the feature

It looks like for EF Core support we've missed one of the features of ValueComparer - overriding the snapshot function.

The current implementation is like this (record struct)

public class EfCoreValueComparer : global::Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<ModuleVersion>
{
    public EfCoreValueComparer() : base(
        (left, right) => DoCompare(left, right), 
        instance => instance._isInitialized ? instance.GetHashCode() : 0) 
    { 
    }
    
    static bool DoCompare(ModuleVersion left, ModuleVersion right)
    {
        // if neither are initialized, then they're equal
        if(!left._isInitialized && !right._isInitialized) return true;
        
        return left._isInitialized && right._isInitialized && left._value.Equals(right._value);
    }
}

I would suggest to update with with a simple Copy() function to override the Snapshot feature

public class EfCoreValueComparer : global::Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<ModuleVersion>
{
    public EfCoreValueComparer() : base(
        (left, right) => DoCompare(left, right), 
        instance => instance._isInitialized ? instance.GetHashCode() : 0, 
        instance => instance.Copy()) // new code here
    { 
    }
    
    static bool DoCompare(ModuleVersion left, ModuleVersion right)
    {
        // if neither are initialized, then they're equal
        if(!left._isInitialized && !right._isInitialized) return true;
        
        return left._isInitialized && right._isInitialized && left._value.Equals(right._value);
    }
}

As for the Copy() implementation - if it's a struct or a class record something like instance with {} could be used, but a general case would be to call either new VOTYPE() if not initialized or new VOTYPE(instance.Value)

@Aragas Aragas added the enhancement New feature or request label May 21, 2024
@CheloXL
Copy link

CheloXL commented May 22, 2024

@Aragas Why would you like to have a copy? VO should be immutable. If you have state in your VO, something is wrong... also, if the VO is a struct, you always get a copy anyways...

@Aragas
Copy link
Author

Aragas commented May 23, 2024

@Aragas Why would you like to have a copy? VO should be immutable. If you have state in your VO, something is wrong... also, if the VO is a struct, you always get a copy anyways...

Immutability and the ability to have a copy of an immutable object do not conflict with each other. We still have Vogen class types where a copy will provide a different reference.
Also, we have no restrictions with forcing the underlying type of Vogen to be a struct type, so perhaps having a virtual method that correctly copies the underlying type when it's a reference type might be nice to have.

@CheloXL
Copy link

CheloXL commented May 23, 2024

Well, I'm not opposed to the Copy method (although you can manually implement it if you really need). As for the change into EF value comparer, I'm against it, as it doesn't add anything to the existing functionality, and if you are using reference types, you are actually increasing memory usage in exchange of nothing.

@Aragas
Copy link
Author

Aragas commented May 23, 2024

Well, I'm not opposed to the Copy method (although you can manually implement it if you really need). As for the change into EF value comparer, I'm against it, as it doesn't add anything to the existing functionality, and if you are using reference types, you are actually increasing memory usage in exchange of nothing.

It doesn't matter whether a reference type increases memory usage. Vogen is a tool that has multiple ways of usage. If the user decides to use reference types - we need to make sure that the integration we provide always works.
Adding the a manual snapshot expression actually increases the performance, since the generic code that is used as a fallback is slower

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

No branches or pull requests

2 participants