42 Replies
I'm not quite sure how to handle the cases where:
1) The entry does not yet exists. Create and save.
2) The entry exists. Update and save.
I've been having some issues, including but not limited to:
System.InvalidOperationException: The instance of entity type 'ConfigurationData' cannot be tracked because another instance with the same key value for {'PlayerProfileId'} is already being tracked.I think I understand
Add
correctly. But I'm not sure if Update
does what I think it does.This means that you are attempting to use tracking queries for the same entity on two different dbcontexts
Right. I kind of get that, but. How? Where? What's the concrete issue?
The concrete issue is holding multiple instances of your
DbContext
in memory somewhere
for example, say you decide to reuse a dbcontext
you load some data with it, and it starts tracking PlayerProfile
with an id of 5I thought I'm supposed to instantiate a new DbContext every time I want to access something from the database.
yes, i am giving an example of how newcomers with EF tend to misuse it
All right.
but I also don't know why you're directly using a
DatabaseConnection
if you're trying to use EFCoreIt's what I call my class:
https://gist.github.com/Pilvinen/fa99bc00be16431981373e9dec1542f7
ah, I would suggest naming it
<Something>DbContext
personally as it also exposes a database connection under <dbContext>.Database.Connection
Ah, okay. I will rename it to
GameDbContext
.
I still didn't quite understand where I'm going wrong.Is this the only place where you're using your dbcontext?
my guess is that you're not properly disposing of one somewhere
but without seeing more code it is hard to tell
Well, I'm using it in 22 different places, I believe.
either that or you are running into an issue with concurrency and you are attempting to do two different things, with two different dbcontexts, which affect the same entity
And they should all be contained inside using statement.
It's not the
Find
which might be messing up with it?
I'm not sure how to otherwise check if I need to Add or Update.personally, I use the presence of an ID field in my DTOs to determine which actions I need to take
as you can do something like this to update a row without fetching it first, assuming you know it exists
I used to have a singleton based approach where I kept the DbContext alive for the duration of the app.
Because I'm using SQLite with EF Core.
But I had weird issues where save took 30 ms.
So I thought I'd give this a try if it works better by doing the whole "unit of work".
But I'm still not sure what I'm doing wrong. I can't get it working at all.
https://gist.github.com/Pilvinen/b9d17081c626e17ae57824428cda723e
It can't be anything in here, right?
No, it shouldn't be anything in there
Here's one example how I call those methods.
It fails on the SaveData call and inside the method specifically on the Update call.
what does
ConfigurationDataService.LoadData
look like?
but loading and saving using 2 different dbcontexts feels like an anti pattern
it should be done with the same one
otherwise you are throwing away EFs ability to use change tracking
This works? Why? What's the difference?
what was it before the change?
Update(). The one I commented out there.
my guess is that doing it this way prevents it from trying to load another instance of the entity, but I'm not sure
I still wouldn't structure your methods this way
I will try to inject the dbContext to get around not using a single context.
As you suggested.
it is more than just that, your method of loading the db context, returning it, making modifications, and then saving it using another dbcontext isn't very good
Yes, that's what I meant.
I will inject the dbContext to fix that.
:PepoSalute:
I mean like this:
So now they would share the same context.
I was trying to get rid of database specific calls in my code.
Which is why I was doing that in the first place.
that is also generally considered an anti-pattern when it comes to EFCore
But apparently it was not a good idea.
Really?
as the
DbContext
is your repositoryWhat's the proper way then?
imo it really comes down to personal preference
I mean, what options do I have?
I'd put that entire method in your configuration service
and let it handle all of the entity framework stuff
then expose
ConfigurationDataService.SetDeckBack
which does everythingOh so I would just relay it forward .. or maybe combine Configuration.cs with ConfigurationDataService.cs 🤔
Because it's now starting to feel silly why it even exists separately.
:Blob:
takes a bit to get used to how to structure code using EF if all you've used is raw sql
This is actually my first time ever using databases from C#.
Which makes it even harder.
once you figure out some of the small issues like this efc gets much easier to use
But why is it an anti-pattern passing the dbContext as a parameter to a function?
passing it in isn't as bad
but depending on what you're doing there may be no point in creating the dbcontext externally