-
Notifications
You must be signed in to change notification settings - Fork 470
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
Proxies using Records with a base class broken using .NET 6 compiler #601
Comments
This will most likely affect proxying any hierarchy that uses covariant returns. |
@ajcvickers I see that multiple issues have been file in different repos. What is the purpose of having a roslyn issue? How did roslyn misbehave (expected versus actual)? |
@stakx Any chance this can get looked at soon? It's blocking people using dynamic proxies for lazy-load in EF Core on .NET 6. |
@ajcvickers Am I missing something, are you discussing this with Dom via private channels? I can't find any discussion in the linked issues across various projects. I had ignored this issue as you directly mentioned him. |
@jonorossi No, I just pinged him because he seemed to be most active recently on the project. |
Note that this is an issue involving covariant return types rather than .NET 6 per se. I got this error yesterday in .NET 5 after defining a custom Clone() method with covariant return type. |
Fixes #26602 **Description** The C# compiler changed the emit strategy for records in .NET 6 to take advantage of covariant returns. The Clone method now always has a return type that matches the containing type. Castle dynamic proxies throws when attempting to create a proxy for such types. This means EF Core lazy-loading and change-tracking proxies are broken for any record with a base type. An bug has been filed on Castle proxies (castleproject/Core#601), which is the correct place to ultimately fix this issue. However, since EF Core never needs to override the Clone method for its proxies, the fix here simply excludes the Clone method from the proxies we create. **Customer impact** Proxies for records with base types cannot be used. Reported by multiple customers. No known workaround. How found Multiple customer reports on 6.0. Regression Yes, From 5.0 Testing Added unit and functional tests for records with base types. Risk Very low; Clone methods are never used by EF proxies. Also added quirk to revert to previous behavior.
Note: we were able to patch EF with a workaround for the common case (by excluding the method), but this doesn't work for abstract record base types, so this fix is still important for EF. See dotnet/efcore#27491 |
Unassigning from v5.0 milestone. No one was contributed or is discussing a possible fix. |
So am I correct that this prevents making proxies of any record that inherits from an abstract base record? |
I don't think this just impacts abstract records. No one has put together a set of tests using just DP, so I'm not across the full impacts. |
Bump? 🤔 |
@CesarD, this hasn't been forgotten. I'd like to fix a few things in DynamicProxy (this issue included, i.e. support for covariant return types; if time permits), but have been awaiting the now-imminent DynamicProxy v5 release. I'm planning to start working on open issues in about 2-3 weeks' time. |
I've taken a first brief look. The problem appears to be that |
I've put together a little something that may resolve this. See PR linked above. I am admittedly a little out of touch with modern C# (as I haven't spent all that much time in .NET world during the past couple of years). So I am open to suggestions for further important covariant method return scenarios not currently covered by the newly added |
Any idea when this is going to be released? |
All merge requests that make code changes are currently merged, think we could do a minor/patch release at this point @jonorossi? (I'm working on new interface capabilities support, but that's going to take some more time, so there's no need to wait for it at this time.) |
@stakx sorry for the silence on this end. Could you create a release issue with a proposed version number. |
@ajcvickers @CesarD I've just pushed a release including a bugfix for this to NuGet. Hope this helps! |
@stakx Thanks! Much appreciated. |
Thank you so much!! Cheers!! |
One question: should this also work for a generic abstract record? I'm having issues with a case like that, but not really sure so far... |
@CesarD, yes, I'd say this should work as well. Are you using Please open a new issue for this once you're sure / have some repro code. |
Yes, I am using it as part of the return type of a Command I'm using with MediatR... And when mocking (with Moq) commands inheriting from this base (generic) abstract command, it throws the exception when accessing the I'll try to get some repro code for tomorrow. |
Hi @stakx! I've just tried some repro code using Moq, which is my use case, and it turns out to effectively occur with only generic abstract records. Here goes the code: var mock1 = new Mock<MyDerivedRecord>();
var mock2 = new Mock<MyDerivedGenericRecord>();
var a = mock1.Object;
var b = mock2.Object;
public abstract record MyBaseRecord
{
}
public abstract record MyBaseGenericRecord<T>
{
public T Prop { get; set; }
}
public record MyDerivedRecord : MyBaseRecord
{
}
public record MyDerivedGenericRecord : MyBaseGenericRecord<int>
{
} Variable
If you still wish, I can open a new issue based on this. Please let me know. |
Yes, please open a new issue. Thanks! |
See original issue here: dotnet/efcore#26602
Attempt is made to proxy this:
Comment from Jared Parsons on the C# compiler team:
Full repro: https://github.com/Jejuni/Net6RecordEfCoreProxies
Stack trace:
The text was updated successfully, but these errors were encountered: