dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.77k stars 3.19k forks source link

Fully support complex types with the InMemory provider #31464

Open roji opened 1 year ago

roji commented 1 year ago

Some query/materialization support is missing, see tests DbContextTest.SaveChanges_calls_DetectChanges_by_default, DbContextTest.Auto_DetectChanges_for_SaveChanges_can_be_switched_off

ajcvickers commented 1 year ago

Note from triage: we are very unlikely to implement this. See https://github.com/dotnet/efcore/issues/18457#issuecomment-615411282

aliastopan commented 9 months ago

Is the KeyNotFoundException part of the reason why ComplexProperty has yet compatible with in-memory database?

"title": "KeyNotFoundException", "code": 500, "source": "System.Private.CoreLib", "detail": "The given key 'Property: UserAccount.User#User.EmailAddress (string) Required MaxLength(255)' was not present in the dictionary.", "stackTrace": [ " at TValue System.Collections.Generic.Dictionary<TKey, TValue>.get_Item(TKey key)", " at Expression Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor+ShaperExpressionProcessingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)",

roji commented 9 months ago

@aliastopan support hasn't been done for InMemory, this specific KeyNotFoundException may be part of that (or not). We're unlikely to implement support, since using the InMemory database for testing is discouraged - consider testing against your containerized database (e.g. SQL Server) using testcontainers.net.

IanWitham commented 1 month ago

Is this documented somewhere? I've just sunk hours into trying to "solve" this before I came across this thread.

roji commented 1 month ago

@IanWitham yes, the InMemory provider documentation contains the following note:

New features are not being added to the in-memory database.

Aside from the numerous other warnings and notices to stay away from the provider in general.

marchy commented 1 month ago

@roji the right guidance to give on that page would be to suggest people to use the SQLite with in-memory option set.

There are definitely gaps there as well, but they are more or less workable and has been a godsend to enabling us to work in a rapid development model for new features (ie: not having to worry about migrating a live DB until you have the full domain model for that feature built out)

roji commented 1 month ago

the right guidance to give on that page would be to suggest people to use the SQLite with in-memory option set.

We generally recommend against using database fakes, either InMemory or Sqlite - though Sqlite is indeed a much better option. In today's world, setting up SQL Server or PG via testcontainers and testing against that is both easy and very fast, and so testing against a fake is much less needed than it used to be.

not having to worry about migrating a live DB until you have the full domain model for that feature built out

You can just use EnsureCreated during rapid development, including with a real database - no need to deal with migrations.

marchy commented 1 month ago

@roji What about tests? We run all tests on Sqlite DB's that we create rapidly for each test instance (ie: in test creation/tear-down)

Can this run disconnected from the Internet on local and test servers?

It looks like a LOT more setup to pull off – but if that is indeed the guidance there should be a full guide for how to set it up in both local environment and Azure DevOps at the least.

roji commented 1 month ago

@marchy tests is what we're discussing here above (at least what I was discussing).

Can this run disconnected from the Internet on local and test servers?

Of course, the major databases can run in a docker container, which is very easy to manage. As I wrote above, I suggest taking a look at testcontainers, and also reading the EF testing docs which discuss a lot of this stuff.

jukkahyv commented 1 month ago

Of course, the major databases can run in a docker container, which is very easy to manage. As I wrote above, I suggest taking a look at testcontainers, and also reading the EF testing docs which discuss a lot of this stuff.

Can you give a practical example of how it would work in the ideal situation? I mean some medium-large open source website that makes use of testcontainers to efficiently run 100s of tests. Because the problem is, I've only seen bad examples. Projects that try to do it that way, then 2-3 years afterwards it takes 20 minutes to run the tests, tests randomly fail because of database timeouts, and test data management is a nightmare because it's being reused between tests. I'm not against using real database for tests, I just haven't seen it working.

roji commented 1 month ago

@jukkahyv please take a thorough look at the testing docs I linked to above; these are also related to these code samples which should be helpful. I do think we should improve these docs to specifically show testing with testcontainers (they were written before that was a thing), and be more practically-oriented, but the general idea is there.

EF itself runs almost all of its test against real databases - that's around 20k tests that run against SQL Server alone, in a very reasonable amount of time. It's a matter of structuring test databases appropriately, not e.g. creating one for every test, and running everything in parallel while ensuring that modification tests e.g. use transactions which get rolled back, so as to not cause interference with other tests.