-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Support immutable entity updates #11457
Comments
Some notes from a recent discussion: One way EF Core could work with immutable objects is that immutability also extends to the database, so you can insert, and maybe delete, but never ever update any row. Another approach that seems more pragmatic would be to provide a way to explicitly replace one tracked immutable object with another one with the same key (or if the key is in shadow state, just replace it assuming it has the same key). It is possible that this coudl be implemented by extending other other functionality that already exists in EF Core in some form or at least are in our roadmap. Here are some ideas/questions:
|
Is there any update on plans for supporting immutable entities? |
@richardpawson This issue is in the Backlog milestone. This means that it is not going to happen for the 3.1 release. We will re-assess the backlog following the 3.1 release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources. |
With C# 9 records, this becomes a bit more relevant. Apart from allowing the user to replace a tracked instance with another (Replace or non-throwing Attach), we could imagine a proxy-based system that would leverage that. For example, the With methods on record types could be wrapped so that it calls Replace on the DbContext with the new instance. |
@ajcvickers Please please please if and when you look at this, spend just a tiny bit of time getting this working with F# records too. Under the hood, F# records are just C# classes with a single non-default constructor that has parameters for every field on the record, and getter-only properties for each field. This is probably one of the main issues stopping people using EF on F# - there's just too much friction at the moment. |
@isaacabraham we unfortunately probably won't have time to look anytime soon, but it would be useful to know more about how mutation works with F# records. The new C# records have the with pattern, does something similar exist in F#? |
Actually, C# copied records from F# https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/copy-and-update-record-expressions |
OK, thanks. It's safe to say that if/when we do get around to supporting updates for immutable types, that would include C# records, and therefore probably also support F# records. |
@roji great. Just to clarify, by "probably", does you mean that either:
Thanks! |
@isaacabraham it's too early to say exactly how we'll approach this and what scope we'll have, as we don't plan to work on this right away. However, assuming there isn't going to be a major, fundamental difference between F# and C# record support, I indeed expect us to specifically target F# support as well. |
Hello, is there some workaround in EF Core 5.0.1 if I have all entity types immutable? I tried both Tracking and NoTracking, but neither did work. |
@RichardBlazek for NoTracking queries, things should work well - please open a new issue with a full code sample and error message. |
I found this workaround (https://stackoverflow.com/a/57892450) for anyone who is still looking... contexts
.Entry(requests.Find(request.Key))
.CurrentValues
.SetValues(request);
contexts.SaveChanges(); I'm no sure if this has unintended consequences compared to using |
@jtleaming I believe what you are doing with that workaround is mutating the values of properties (essentially, but not actually, by Reflection) of what is intended to be an immutable object. So I'm not sure it is really a valid workaround if you are really trying to work with immutable types. |
@ajcvickers If the intention of immutable types is to protect unintended data changes from happening in code does the database need to follow the same pattern? I was calling Update like this originally. dbSet.Update(request with {
Something = "Changed"
});
context.SaveChanges(); But I was getting |
@jtleaming This issue is about supporting updates for immutable types. How that will happen is not yet defined. |
My 2c is that the final design should not assume that a call to the e.g. both of these should be supported: create a copy with updates:
update:
NOTE: I have added the update method here just to illustrate my point, there may be better ways to design this. |
As a F# newbie, I googled on this issue for days. To me, AsNoTracking with Linq looks horrible in F#. While there is not much progress on this issue, a workaround may help. Maybe there are better ways to do this but the compiler and I are ok to detach the record manually.
|
Currently I am using the following workaround myself:
I wouldn't mind having a
In my opinion this makes it clearer that you know what you are doing and are working with immutable objects/records. The behaviour of the |
Any plans for EF7? |
@xperiandri this isn't currently planned: the milestone above shows it still in the backlog. |
@roji it would be nice to have it at least in EF7 😉 |
@xperiandri Please vote (👍) for this issue if it is important to you. It currently has 36 votes, which puts it at 34th place in the list of top voted issues. See The Planning Process for more information on how we decide what to work on. |
@ajcvickers @roji This looks to be having more votes now. Any plan to consider this anytime sooner. Really curious to know if any further discussions are happening on this internally. Thank you! |
@abdu292 We'll consider it in the normal planning process. There have been no internal discussions. |
Note that with the introduction of ExecuteUpdate/ExecuteQuery, you can now perform (untracked) updates/deletes on immutable entity updates. Of course, that means it's up to you to know what needs to be changed, but that's fine in many scenarios (especially disconnected ones). |
@ajcvickers @roji Thank you! Thanks so much! |
Issue #10703 covers materialization of entities with constructors, which allows immutable entities to be used with EF Core. However, since these entities are immutable it means that they are read-only from an EF perspective--that is, the database row will never get updated. This issue is about enabling patterns in EF that are commonly used with immutable objects, such as creating new instances to represent changes. See also discussion in #3129.
The text was updated successfully, but these errors were encountered: