Entity Framework 6.2 database first warm up - sql-server

I have an EF 6.2 project in my MVC solution.
This uses a SQL server db and has about 40 tables with many foreign keys.
The first query is very slow, 20 secs.
I immediately hit the same page again, changing the user param, and the query takes less than 1 second.
So this looks like a warm up issue in EF6. That's fine and there's loads of things i can do to sort apparently.
The Model cache (part of EF6.2) looks like it could be beneficial, but everywhere i read about it states model first. Nothing about DB first. Would this still work with db first?
Also there's the Entity Framework 6 power tools, these allow for me to Generate Views. Tried this and it doesn't seem to make any difference. Is this still a valid route?
Any other ideas?

EF DbContexts incur a one-off cost to resolve their entity mappings. For web applications you can mitigate this by having your application start up kick off a simple query against the DbContext which "kicks off" this warm-up rather than during your first user-triggered query. Simply new-ing up a context doesn't trigger the initialization, running a query does. So for ASP.Net MVC on the Application_Start, after initializing everything:
using (var context = new MyContext())
{
var warmup = context.MyTable.Count(); // against a small table.
}
You can test this behaviour with unit tests by having a suite of timed tests that read data from the DbContext, and putting a break-point in DbContext's OnModelCreating event. It will be executed just once from the first test with the first query. You can add a OneTimeSetUp in a test fixture setup to run ahead of the tests with the above quick count example to incur this cost before measuring the performance of the test runs.

So, the answer was to update EF to 6.2 then use the newest feature:
public class MyDbConfiguration : DbConfiguration
{
public MyDbConfiguration() : base()
{
var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
SetModelStore(new DefaultDbModelStore(path));
}
}
for the full story check out this link: https://entityframework.net/why-first-query-slow
Your gonna take a small performance hit at startup but then it all moves a lot faster.
For anyone using an Azure web app you can use a deployment slot (https://stackify.com/azure-deployment-slots/), this allow you to publish into a non-production slot then warm it up before swapping it in as the production slot.

Related

Automate the execution of a C# code that uses Entity Framework to treat data?

I have code that uses Entity Framework to treat data (retrieves data from multiple tables then performs operations on it before saving in a SQL database). The code was supposed to run when a button is clicked in an MVC web application that I created. But now the client wants the data treatment to run automatically every day at a set time (like an SSIS package). How do I go about this?
But now the client wants the data treatment to run automatically every day at a set time (like an SSIS package). How do I go about this?
In addition to adding a job scheduler to your MVC application as #Pac0 suggests, here are a couple of other options:
Leave the code in the MVC project and create an API endpoint that you can invoke on some sort of schedule. Give the client a PowerShell script that calls the API and let them take it from there.
Or
Refactor the code into a .DLL or copy/paste it into a console application that can be run on a schedule using the Windows Scheduler, SQL Agent or some other external scheduler.
You could use some tool/lib that does this for you. I could recommend Hangfire, it works fine (there are some others, I have not tried them).
The example on their homepage is pretty explicit :
RecurringJob.AddOrUpdate(
() => Console.WriteLine("Recurring!"),
Cron.Daily);
The above code needs to be executed once when your application has started up, and you're good to go. Just replace the lambda by a call to your method.
Adapt the time parameter on what you wish, or even better: make it configurable, because we know customers like to change their mind.
Hangfire needs to create its own database, usually it will stay pretty small for this kind of things. You can also monitor if the jobs ran well or not, and check no the hangfire server some useful stats.

Reset database after each test on Spring without using DirtiesContext

I would like to know if there is some way to reset the database after each integration test without #DirtiesContext:
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
This works but it is very slow, because the Spring context is reloaded each test.
My tests are using MockMvc, doing rest calls for an API. Like:
mockMvc.perform(put("/products/)
.header("Content-Type", "application/json")
.content(jsonPost))
.andExpect(status().isOk())
.andReturn();
So, without manual intervention (create and maintain a script to drop and create the tables), the Spring framework offer some alternative?
You can clean the tables you need by doing the following:
Inject a JdbcTemplate instance
#Autowired
private JdbcTemplate jdbcTemplate;
Use the class JdbcTestUtils to delete the records from the tables you need to.
JdbcTestUtils.deleteFromTables(jdbcTemplate, "table1", "table2", "table3");
Call this line in the method annotated with #After or #AfterEach in your test class:
#AfterEach
void tearDown() throws DatabaseException {
JdbcTestUtils.deleteFromTables(jdbcTemplate, "table1", "table2", "table3");
}
I found this approach in this blog post:
Easy Integration Testing With Testcontainers
In simple case annotate each your test class as #Transactional and transaction manager will do rollback after each #Test method. Get more information reading this.
I am a bit late to the party, but I had the same problem. All the unit tests (which could be considered integration tests) in an application I inherited took approximately 35 minutes to complete, using an embedded H2 as database for tests. All test classes where annotated by #DirtiesContext, usually method level.
So, the database was destroyed and recreated for each method. This takes time.
By removing the dirties annotation and using a database truncation class in the #Before method I now run the complete test suite in about 4 minutes.
If you have anything else than JPA stuff (not handled by the Entity manager) in your Spring context that should be removed between tests you have to do it explicitly.
I can share the DB truncation class if you like, but it is simply using the JPA meta model to find the tables to truncate. Truncation seems to be very efficient in H2. Exceptions for entities based on views, not tables, can be configured.
To make truncation easier, turn off refererential integrity before truncation and switch it back on when you're done.
You could use org.springframework.test.context.jdbc #Sql({"clear-database.sql"}) and then just write a script to clear the db.
So you'd end up with something like this:
#Test
#Sql({"classpath:sql/clear-database.sql", "classpath:sql/set-up-db.sql"}
void doThings(){
this.mockMvc.perform(etc..);
}

Entity Framework SaveChanges hangs while doing nothing - SQL times out

Here's the story. I've got a generic save web service call that uses Entity Framework to save any entity object. The reasons it's done in this way is, one, there's a very tight schedule for this, and two, we're talking to an old version of Windows Mobile, so there's little support for better, more modern ways of doing this. The meat of this is an array of EntityObjects that's passed into the web service, which then:
Using TESTEntity As New TESTEntities(EntityConnectionString)
For Each change As Object In Changes
Dim item As EntityObject = DirectCast(change, EntityObject)
Dim NewState As EntityState
If (item.EntityKey Is Nothing) Then
NewState = EntityState.Added
Else
NewState = EntityState.Modified
End If
TESTEntity.AttachTo(change.GetType().Name, item)
TESTEntity.ObjectStateManager.ChangeObjectState(item, NewState)
Next
TESTEntity.SaveChanges()
End Using
This function worked fine for a while. It still works fine for us here at development, but it fails strangely at a client. It gets to SaveChanges and then just hangs until a SQLTimeoutException is thrown.
First, I've tried turning up the CommandTimeout value without any luck.
Second, this webservice is called numerous times all over the place, but appears to only fail in one specific place, and only on the client site but not here. We don't have easy access to the client site or database, but we've confirmed that the database schema's match and we're fairly certain their mobile software is the most recent version (We're confirming that tonight).
Third, we've run the SQL profiler on the client's SQL Server and see that the only request that's being made is the Audit Login without any other queries being run. This SaveChanges is only doing a small handful of Inserts and Updates, so it shouldn't be timing out in the first place.
If there was a bad entity object or something about the schema didn't match, I would expect a different exception, or at least the SQL Profiler to show something other than just the Audit Login... I'm at a loss as to what is happening, any thoughts?

How to write unit tests for database calls

I'm near the beginning of a new project and (gasp!) for the first time ever I'm trying to include unit tests in a project of mine.
I'm having trouble devising some of the unit tests themselves. I have a few methods which have been easy enough to test (pass in two values and check for an expected output). I've got other parts of the code which are doing more complex things like running queries against the database and I'm not sure how to test them.
public DataTable ExecuteQuery(SqlConnection ActiveConnection, string Query, SqlParameterCollection Parameters)
{
DataTable resultSet = new DataTable();
SqlCommand queryCommand = new SqlCommand();
try
{
queryCommand.Connection = ActiveConnection;
queryCommand.CommandText = Query;
if (Parameters != null)
{
foreach (SqlParameter param in Parameters)
{
queryCommand.Parameters.Add(param);
}
}
SqlDataAdapter queryDA = new SqlDataAdapter(queryCommand);
queryDA.Fill(resultSet);
}
catch (Exception ex)
{
//TODO: Improve error handling
Console.WriteLine(ex.Message);
}
return resultSet;
}
This method essentially takes in all the necessary bits and pieces to extract some data from the database, and returns the data in a DataTable object.
The first question is probably the most complex: What should I even test in a situation like this?
Once that's settled comes the question of whether or not to mock out the database components or try to test against the actual DB.
What are you testing?
There are three possibilities, off the top of my head:
A. You're testing the DAO (data access object) class, making sure it's correctly marshaling the values/parameters being passed to the database,, and correctly marshaling/transforming/packaging results gotten frm the database.
In this case, you don't need to connect to the database at all; you just need a unit test that replaces the database (or intermediate layer, eg., JDBC, (N)Hibernate, iBatis) with a mock.
B. You're testing the syntactic correctness of (generated) SQL.
In this case, because SQL dialects differ, you want to run the (possibly generated) SQL against the correct version of your RDBMS, rather than attempting to mock all quirks of your RDBMS (and so that any RDBMS upgrades that change functionality are caught by your tests).
C. You're testing the semantic correctness of your SQL, i.e, that for a given baseline dataset, your operations (accesses/selects and mutations/inserts and updates) produce the expected new dataset.
For that, you want to use something like dbunit (which allows you to set up a baseline and compare a result set to an expected result set), or possibly do your testing wholly in the database, using the technique I outline here: Best way to test SQL queries.
This is why (IMHO) unit tests can sometimes create a false sense of security on the part of developers. In my experience with applications that talk to a database, errors are commonly the result of data being in an unexpected state (unusual or missing values etc.). If you routinely mock up data access in your unit tests, you will think your code is working great when it is in fact still vulnerable to this kind of error.
I think your best approach is to have a test database handy, filled with gobs of crappy data, and run your database component tests against that. All the while remembering that your users will be much much better than you are at screwing up your data.
The whole point of a unit test is to test a unit (duh) in isolation. The whole point of a database call is to integrate with another unit (the database). Ergo: it doesn't make sense to unit test database calls.
You should, however, integration test database calls (and you can use the same tools you use for unit testing if you want).
For the love of God, don't test against a live, already-populated database. But you knew that.
In general you already have an idea of what sort of data each query is going to retrieve, whether you're authenticating users, looking up phonebook/org chart entries, or whatever. You know what fields you're interested in, and you know what constraints exist on them (e.g., UNIQUE, NOT NULL, and so on). You're unit testing your code that interacts with the database, not the database itself, so think in terms of how to test those functions. If it's possible for a field to be NULL, you should have a test that makes sure that your code handles NULL values correctly. If one of your fields is a string (CHAR, VARCHAR, TEXT, &c), test to be sure you're handling escaped characters correctly.
Assume that users will attempt to put anything* into the database, and generate test cases accordingly. You'll want to use mock objects for this.
* Including undesirable, malicious or invalid input.
Strictly speaking, a test that writes/reads from a database or a file system is not a unit test. (Although it may be an integration test and it may be written using NUnit or JUnit). Unit-tests are supposed to test operations of a single class, isolating its dependencies. So, when you write unit-test for the interface and business-logic layers, you shouldn't need a database at all.
OK, but how do you unit-test the database access layer? I like the advice from this book: xUnit Test Patterns (the link points to the book's "Testing w/ DB" chapter. The keys are:
use round-trip tests
don't write too many tests in your data access test fixture, because they will run much slower than your "real" unit tests
if you can avoid testing with a real database, test without a database
You can unit test everything except: queryDA.Fill(resultSet);
As soon as you execute queryDA.Fill(resultSet), you either have to mock/fake the database, or you are doing integration testing.
I for one, don't see integration testing as being bad, it's just that it'll catch a different sort of bug, has different odds of false negatives and false positives, isn't likely to be done very often because it is so slow.
If I was unit testing this code, I'd be validating that the parameters are build correctly, does the command builder create the right number of parameters? Do they all have a value? Do nulls, empty strings and DbNull get handled correctly?
Actually filling the dataset is testing your database, which is a flaky component out of the scope of your DAL.
For unit tests I usually mock or fake the database. Then use your mock or fake implementation via dependency injection to test your method. You'd also probably have some integration tests that will test constraints, foreign key relationships, etc. in your database.
As to what you would test, you'd make sure that the method is using the connection from the parameters, that the query string is assigned to the command, and that your result set returned is the same as that you are providing via an expectation on the Fill method. Note -- it's probably easier to test a Get method that returns a value than a Fill method the modifies a parameter.
The first question is probably the most complex: What should I even test in a situation like this?
Since your code code is basically a DAO/repository without any
business logic you need an integration test, not a unit test.
Unit test should test classes without external dependencies (like DB
or calls to other remote services).
You should always try to separate the business logic (your Domain
Model) code from infrastructure code then it will be easy to use unit
tests.
Be careful with Mocks, it can be a signal of bad design. It means
you business logic is mixed with infrastructure.
Check these patterns: "Domain Model", "Hexagonal Architecture", "Functional Core, Imperative Shell"
In order to do this properly though you would should use some dependency injection (DI), and for .NET there are several. I am currently using the Unity Framework but there are others that are easier.
Here is one link from this site on this subject, but there are others:
Dependency Injection in .NET with examples?
This would enable you to more easily mock out other parts of your application, by just having a mock class implement the interface, so you can control how it will respond. But, this also means designing to an interface.
Since you asked about best practices this would be one, IMO.
Then, not going to the db unless you need to, as suggested is another.
If you need to test certain behaviors, such as foreign key relationships with cascade delete then you may want to write database tests for that, but generally not going to a real database is best, esp since more than one person may run a unit test at a time and if they are going to the same database tests may fail as the expected data may change.
Edit: By database unit test I mean this, as it is designed to just use t-sql to do some setup, test and teardown.
http://msdn.microsoft.com/en-us/library/aa833233%28VS.80%29.aspx
On JDBC based project, JDBC connection can be mocked, so that tests can be executed without live RDBMS, with each test case isolated (no data conflict).
It allow to verify, persistence code passes proper queries/parameters (e.g. https://github.com/playframework/playframework/blob/master/framework/src/anorm/src/test/scala/anorm/ParameterSpec.scala) and handle JDBC results (parsing/mapping) as expected ("takes in all the necessary bits and pieces to extract some data from the database, and returns the data in a DataTable object").
Framework like jOOQ or my framework Acolyte can be used for: https://github.com/cchantep/acolyte .
Perhaps, a good approach would be to test the behaviour of your domain logic that communicates with the DB under the hood.
Without diving into DDD and CQRS, you could check out DbSample on GitHub, a sample EF Core based project with fully automated tests against services that work with MS SQL Server. It also has a GitHub Actions pipeline to run the tests in cloud builds.
An example of the test would be
[Fact]
public async Task Update_Client_Works()
{
// GIVEN a DB with a client
var existingClient = await DataContext.AddAsync(new Client { Name = "Name" });
await DataContext.SaveChangesAsync();
var clientId = existingClient.Id;
// WHEN update name of the client (this domain command executes an SQL query)
await _clientCommandService.Update(clientId, new CreateUpdateClientRequest("XYZ"));
// THEN the name is updated
var client = await DataContext.Clients.FindAsync(clientId);
Assert.Equal("XYZ", client!.Name);
}
For a deeper dive into orchestrating tests, see "Pain & Gain of automated tests against SQL (MS SQL, PostgreSQL)" article. It goes into the woods of "how?" and "why?". Spoiler alert – it relies on Docker a lot.

How do I unit test persistence?

As a novice in practicing test-driven development, I often end up in a quandary as to how to unit test persistence to a database.
I know that technically this would be an integration test (not a unit test), but I want to find out the best strategies for the following:
Testing queries.
Testing inserts. How do I know that the insert that has gone wrong if it fails? I can test it by inserting and then querying, but how can I know that the query wasn't wrong?
Testing updates and deletes -- same as testing inserts
What are the best practices for doing these?
Regarding testing SQL: I am aware that this could be done, but if I use an O/R Mapper like NHibernate, it attaches some naming warts in the aliases used for the output queries, and as that is somewhat unpredictable I'm not sure I could test for that.
Should I just, abandon everything and simply trust NHibernate? I'm not sure that's prudent.
Look into DB Unit. It is a Java library, but there must be a C# equivalent. It lets you prepare the database with a set of data so that you know what is in the database, then you can interface with DB Unit to see what is in the database. It can run against many database systems, so you can use your actual database setup, or use something else, like HSQL in Java (a Java database implementation with an in memory option).
If you want to test that your code is using the database properly (which you most likely should be doing), then this is the way to go to isolate each test and ensure the database has expected data prepared.
As Mike Stone said, DbUnit is great for getting the database into a known state before running your tests. When your tests are finished, DbUnit can put the database back into the state it was in before you ran the tests.
DbUnit (Java)
DbUnit.NET
You do the unit testing by mocking out the database connection. This way, you can build scenarios where specific queries in the flow of a method call succeed or fail. I usually build my mock expectations so that the actual query text is ignored, because I really want to test the fault tolerance of the method and how it handles itself -- the specifics of the SQL are irrelevant to that end.
Obviously this means your test won't actually verify that the method works, because the SQL may be wrong. This is where integration tests kick in. For that, I expect someone else will have a more thorough answer, as I'm just beginning to get to grips with those myself.
I have written a post here concerning unit testing the data layer which covers this exact problem. Apologies for the (shameful) plug, but the article is too long to post here.
I hope that helps you - it has worked very well for me over the last 6 months on 3 active projects.
Regards,
Rob G
The problem I experienced when unit testing persistence, especially without an ORM and thus mocking your database (connection), is that you don't really know if your queries succeed. It could be that you your queries are specifically designed for a particular database version and only succeed with that version. You'll never find that out if you mock your database. So in my opinion, unit testing persistence is only of limited use. You should always add tests running against the targeted database.
For NHibernate, I'd definitely advocate just mocking out the NHibernate API for unit tests -- trust the library to do the right thing. If you want to ensure that the data actually goes to the DB, do an integration test.
For JDBC based projects, my Acolyte framework can be used: http://acolyte.eu.org . It allows to mockup data access you want to tests, benefiting from JDBC abstraction, without having to manage a specific test DB.
I would also mock the database, and check that the queries are what you expected. There is the risk that the test checks the wrong sql, but this would be detected in the integration tests
I usually create a repository, use that to save my entity and retrieve a fresh one. Then I assert that the retrieved is equal to the saved.
Technically unit tests of persistance are not unit tests. They are integration tests.
With C# using mbUnit, you simply use the SqlRestoreInfo and RollBack attributes:
[TestFixture]
[SqlRestoreInfo(<connectionsting>, <name>,<backupLocation>]
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
[RollBack]
public void TEST()
{
//test insert.
}
}
The same can be done in NUnit, except the attribute names differ slightly.
As for checking, if your query iss successful, you normally need to follow it with a second query to see if the database has been changed as you expected.

Resources