SQLite memory database eager loading entities - c#

I've switched our tests to use a SQLite :memory: database over a database file in an effort to speed up our tests. Everything has gone smoothly, except for one caveat: it's automatically eagerly loading navigation properties on entities.
If I run the project and hit it with Postman using an actual database file, it doesn't eagerly load them, and only loads navigation properties if I specify I want them using .Include().
It didn't do this before I switched to a SQLite Memory database for the tests.
The DbContext configuration is as follows:
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = false;
Configuration.ValidateOnSaveEnabled = true;
Has anyone run into this issue before?

This is an old post, but I thought I'd provide an answer for anyone else that stumbles upon this.
What is likely happening here is simply that your DbContext has the entities cached in its ChangeTracker. Regardless of the underlying provider, when you insert an entity into the database, Entity Framework tracks that entity. If you query for an entity you just inserted, Entity Framework assumes the entity would not have changed and therefore returns the entity from the ChangeTracker. If you changed your query to do a _myDbContext.Set<SomeEntity>().AsNoTracking().ToList() then you should find that it performs a query and only prefetches related entities you've specified.

Related

EF Core is sharing tracked entities across instances

I am using EF Core 3.1.26 with EntityFrameworkCore.Jet 3.1.1, using MS Access for the database. I would update EF Core, but then it wouldn't be compatible with EntityFrameworkCore.Jet.
My problem is that there seems to be some kind of static cache shared across instances. When after creating a instance I attach a entity, it throws an error because the entity is already being tracked, even though it is the first entity attached to that context (the queries are marked with AsNoTracking). I even checked with the debugger that there are no entities in the Entries property of the Change Tracker.
Even when I execute SaveChanges(), entities are updated that shouldn't exist in that context, since I made no query whatsoever. In the Entries property there is only the entity I attached with is navigation properties to null. And yet a bunch of entities of different tables are updated. Those entities I did query, but in another context and with AsNoTracking.
I have no idea where EF Core or EntityFrameworkCore.Jet are getting this entities from. It is like Attach and SaveChanges are accessing a static Change Tracker, and I don't know how to solve this problem.
Thank you.
Edit: It was my mistake, I didn't check correctly.

How to update / synchronize DbContext after external changes to the database

I am using Entity Framework 6 where, for performance reasons, I load my entities into my DbContext up front and then use them locally. Up to now, all changes to the database have gone through the DbContext so my local entities and the database have been in sync. However, I now have to call a Stored Procedure on the database, which has the side effects of making changes to tables (outside of the DbContext) that need to be reflected in my entities. By changes, I mean it is adding new records and deleting / updating existing records.
I do not want to dispose of my DbContext and create a new one, as some of the entity instances are wrapped within ViewModel classes. So, deleting the DbContext in this way would lead to major problems in the UI.
It is my understanding that simply calling Load() on all my DbSets of the DbContext will just replace the existing instances. So, any objects using the old entities instances won't work.
So, I thought I could use the Reload method like:
context.Entry(entity).Reload();
which would update my local entities, but I can only do this for the entities that the DbContext already knows about. It doesn't cover any NEW entities or DELETED entities that were created / deleted as a result of the Stored Procedure executing.
So, I am looking for a way to:
Load, from the database, entities that are NEW to my DbContext
Reload existing entities in my DbContext
Remove any deleted entities from my DbContext
Here is the official documentation for Entity Framework.
Starting from the analysis of your database situation, it suggests smart and quick ways to obtain what you want, detailing when necessary data-read strategies (like eager or lazy loading) or providing tutorials to correctly use code generation and the Wizard GUI.
http://www.entityframeworktutorial.net/choosing-development-approach-with-entity-framework.aspx
Here some more detailed info and tutorial on data-read strategies:
https://www.c-sharpcorner.com/article/eager-loading-lazy-loading-and-explicit-loading-in-entity-framework/
As I already told you in comments, I would suggest a database-first approach and with lazy loading to avoid uncontrolled data behaviours (or reloading the whole db when running a stored procedure).
Talking about the SP, it can simply be mapped through the Wizard that comes with Entity Framework and wrapped by a method.
Hope you will find these resources helpful!
In general EntityFramework can not aware on change in database and update dbcontext .there is no optimized or EntityFramework built-in solution for it.
I think you can use CDC in SqlServer, push change to your application and update your dbcontext. But it not acceptable solution for all business and senario

Entity Framework Decimal Truncation Issue

The project I'm working on uses Entity Framework 6.0 Code-First.
One of my co-workers, due to his lack of experience with EF, manually changed the field type of a field on the database to being decimal(28,10), instead of doing it the correct way in the OnModelCreating method of DbContext. Entity Framework allowed him to do so, never throwing an error upon any future migrations.
Last week, another co-worker was running into a problem with a process that clones records from that table, where the decimal values in the new records were being truncated to 2 decimal places (with no rounding occurring).
The code for that cloning resembles the following (using the Repository pattern on top of EF):
public void CloneAccounts(List<Account> accounts, int newQuarterID)
{
var newAccounts = new List<Account>();
accounts.ForEach(account =>
{
var clonedAccount = new Account
{
QuarterID = newQuarterID
AccountName = account.AccountName,
AccountNumber = account.AccountNumber,
Amount = account.Amount
};
newAccounts.Add(clonedAccount);
});
AccountRepository.AddMany(newAccounts);
AccountRepository.Save();
}
When I pointed out, as a side-point, that the declaration of the Amount field being decimal(28,10) should really be in OnModelCreating, he went ahead and did that, and added a migration. Doing that, interestingly enough, ended up solving the issue with the code above.
My question is two-fold:
Why did that issue not affect the creation of the original records as well, and only upon cloning?
Why did adding that line in OnModelCreating fix it?
Thanks!
If you didn't originally have any precision set, the default convention for code-first is to create decimal columns with precision of 18 and scale of 2 (so only two decimal places). I think it's possible the records had originally been truncated in the first place.
Also, by default, the SQL Server provider's SQL generator sets SqlParameter.Scale property to the scale defined in the model, unless you had TruncateDecimalsToScale set to false, which would affect database updates and inserts. I'm not sure how those records with additional decimal places ended up in the database, though.
When using codeFirst with EF it creates the model in code (C# or VB), then it replicates the model to your DB.
To answer your questions I could say that:
The issue did't affect at first because when you created your model all the changes were made directly to your DB, then you had your tables exactly the same as in the model.
Remember that Entity Framework is an ORM (Object Relational Mapper) it creates, for you and with little effort, a set of entities (classes) based on a domain model -- this domain model can exists it three different flavours: code-first, model-first, and database-first.
Code-first means that you start your project by creating a set of classes (aKa Entities) which will represent your relational model in your data base. (your source will be your classes and the target your database).
Model-first means that you start your project by using a visual tool, basically drag and drop, connecting points and so on, which lets you create a model which will represent your relational model in your data base. (your source will be your model and the target your database).
Database-first means that you start your project by selecting the model from a data source (usually a database), this approach will create for you a set of classes (Entities) in your visual studio project. (your source will be your database and the target your code).
So, whatever change you make in any of the above scenarios must be replicated from source to target via Entity Framework.
What happened here was a mistake from your co-worker, who made a change directly in your database, but it must had been done from your EF project (code first).
When you invoked ClonneAccounts EF made all the magic (connect to DB, execute a query, gets data, cast it to your entity classes, and then retrieve them or visceversa) --> this is when your app crashed because of an InvalidCastException.
EF does not check consistency, scheme or structure of your tables every time you invoke ClonneAccounts, it just retrieves data between Entities and Database and insert/update data. If you want to update/check consistency and replicate changes you have to do it manually. That is why until you fixed your model in the "code side" and ran the tool it replicated all changes to your db.
Hope it helps

Entity Framework Save not working

I am using Entity Framework to save some data in a SQLite database file.
This is my table in DB file
ID Name Username Pwd
ID is autoincrement, and rest of columns are of Text type
This is how I am saving my data into the database:
UserInfo userInfo=new UserInfo();
userInfo.Name="abc";
userInfo.Username="xyz";
userInfo.Pwd="123456";
using (var context = new ApplicationContext())
{
context.UserInfo.Add(userInfo);
context.SaveChanges();
}
The problem is, this code is not inserting any new row into the table. I also tried this before saving, but no luck
context.Entry<UserInfo>(userInfo).State = EntityState.Added;
context.ChangeTracker.DetectChanges();
I tried debugging and no exception is occurring.
How can I insert new row into a table using Entity Framework?
Possibilities that may cause an issue.
Right Click on your Entity Data Model and Update Model From Database. To make sure you have updated till the last change.
Make sure you are looking at the correct Database and Table. Every one makes this mistake once in a while.
Make sure you are using the valid connection string. Pointing the proper databases. Make sure its not a old db / some other backup db.
Make sure you are using the proper entity which is up to date.
The above code you have, its perfectly working fine to me. I just did a workout to sort out this issue.
The above points are guesses.
Refer this Link Entity Data Model Example & One More Example Code available here
I had a similar problem once and it can be a pain to determine what exactly causes this. One issue that might be causing such a behavior in EF is having multiple instances of the Context object such that when you call SaveChanges on your Context, you are actually calling it on a different instance than the one you added the entity on (and EF does not detect any changes in the entities or the new entity is not attached to the right context, causing SaveChanges to not send any SQL requests to the database).
I suggest debugging this in VS (using the object id feature) in order to see if you have multiple context instances. Using the Unit Of Work pattern together with repositories is a way to have a better control over the lifetime of the context objects in your application

What is happening behind EF SaveChanges()

Assume that I have a domain object which has association with couple of other entities (ofcourse mapped to multiple tables). And I made changes in master and associated entities. Naturally EF has to update this in multiple tables on save.
Whether it be ObjectContext or DbContext, a call to SaveChanges() method will tell Entity Framework to "Saves all changes made in this context to the underlying database."
Could anyone tell me "What is happening behind SaveChanges()"?
Is all resulting sql statements INSERT/UPDATE/DELETE goes to database in one go as prepared statement?
or is EF doing back and forth with DB to execute the sql statement one by one?
Is there any configuration in EF to switch between this?
At the moment statements for CUD operations are not batched. We have a work item to fix this. Feel free to upvote
From what I understand, each modified entity will result in a roundtrip to the database (all bound by a single transaction). While I'm not aware of any configuration that will change this behavior, I won't say that there are not EF implementations out there that achieve this "batching" functionality. I just don't think they are available, out of the box.

Categories

Resources