Why am I getting DbContext Has Changed exception when using NUnit? - c#

I'm using Entity Framework 5 in my project. And I wanted to test some new funcionalities.
What happened is that eventhough my db is UPDATED, (when I add a migration it does not add anything else) and eventhough if I run my project it runs just fine. When I try to test the project with NUNIT I get this exception:
System.InvalidOperationException : The model backing the 'DbContext' context has changed since the database was created. Consider using Code First Migrations to update the database
Has any of you have this problem? If so how can I solve it?

Well, my original answer got deleted, guess because it wasn't really an answer as much as a statement that I had the same problem. At this point I have found an answer of sorts, so maybe this one will pass muster.
Of course, I only assume we are having the same issue, but it seems pretty likely since the symptoms are exactly the same. What I discovered is the connection string for my repository was not getting set correctly even though I had set it up "correctly" in a config file using the MyTestProject.dll.config naming convention. Seems like NUnit isn't using the connection string from the config for some reason.
I've set up a temporary solution where I use a different constructor that forces the correct connection string for my repository when creating it for NUnit. Easy to implement this since I'm using DI to create the repository and just need to ask the factory for a different flavor when testing. Working now to figure out why NUnit doesn't use the config file as it seems like it should.
Maybe not a complete answer, but at least this solution got me back to where I can test... We'll see if this one gets deleted.

Related

Controlling values in .NET 6 templates

I have a .NET 6 solution template that I maintain. Like other templates, if the user chooses "Foo" as the name of the solution, the C# namespaces have the sourceName value replaced with Foo, along with class names that have the sourceName value in them. For instance, if you choose to have EF in the output, you'll get an IFooDbContext.
However, if you run the template with a period in the name, bad things happen. For example, dotnet new mytemplate -n Foo.Bar, I get a class called IFoo.BarDbContext, which is clearly not valid C#.
Is there a way in the dotnet templating system to remove the period so that if comes out as IFooBarDbContext? I've spent about an hour looking around on Google prior to posting this question, but didn't see anything obvious. If the answer is no, I'll just require that the user specify the name of the DbContext should they choose to include EF.
Thanks in advance!
Ultimately, I was still not able to figure out a good way to do this. My Entity Framework DbContext class, in the template, is named in a way that it will be replaced with the project name when creating a new project. I decided to just rename the DbContext class to ApplicationDbContext. Now, with or without a dot in the name doesn't matter, as the EF DbContext class is not renamed. The end user can rename the DbContext themselves if they want to via a new parameter that I'm adding in; otherwise it just stays as ApplicationDbContext.
Thanks for taking a look, but I'm going to go ahead and move on from this, having found a solution that will work.

EF6 Complaining that unused Model has no Key

I just spent some time resolving the strangest bug, and I can't figure out why it happened. Maybe someone can follow along and shed some light on why...?
tl;dr: lightweight MembershipContext fails due to some completely unrelated object not having and ID field, but only does so when running under MVC: all integration tests that make sure this stuff works correctly... they work correctly.
What I Have:
I have a solution with a number of projects. The pertinent ones are:
LPA.Domain (contains POCOs for business objects/behavior)
LPA.Data (contains EF6 stuff with FluentAPI config and references LPA.Domain)
LPA.Web (contains an MVC project, refs Data and Domain)
This is a very normal setup for us and the project has been in development for some time with no issues.
Within the Data project I have two DbContexts that are used. One, MembershipContext is used only during login and bypasses the user-based audit system to validate the user. The MembershipContext has only three entities: User, UserMembershipDetail and UserRole.
The second, CoreContext has all the normal stuff (including tracking the currently logged in user ID for audit purposes). This has many entities.
What I Did:
Now let's pretend I spend a few days doing some domain-level development. I add handful of classes, set up their db counterparts, build the models (in CoreContext, MembershipContext doesn't change), write integration tests for the models and unit tests for the domain work. All is well. I haven't touched MembershipContext at all.
Part of what I did was add a new class to LPA.Domain to deal with an object called Matter (legal matter). This was to mock up a single method I needed elsewhere, but was not set up in the db (yet). I added an Ignore() on the appropriate entity and will flesh it out later. No biggie, right? All still happening in the CoreContext
What Happened:
I get done with a few days of domain-level development, then go to fire up the LPA.Web project and hit a strange error when trying to log in. Some digging around tells me basically this:
When trying to get from Users in MembershipContext, it's throwing an exception saying that the LPA.Data.Matter EntityType has no key.
A couple confusing things about this:
LPA.Data.Matter is not an object. The Matter object resides in the LPA.Domain.Legal namespace. Presumably this is an internal thing with EF6 as it creates it's own object to deal with things. Ok, I can buy that...
MembershipContext makes no use of Matter at all. The three objects it does make use of have no downstream references (shallow or deep) to the Matter object.
Integration Testing to build/retrieve the MembershipContext.Users works fine! (Users being the offending Entity in the exception) I think this must indicate some different method between how the LPA.Web project is loading the LPA.Data.MembershipContext as opposed to how the test project is, but that doesn't make much sense to me...
This Matter object is used in testing for the domain project and the LPA.Data.CoreContext tests without issue, why does it fail on the Membership and only when using it through an MVC project?
How I Fixed It:
As noted, I added the Matter class as a quick helper on the domain but hadn't fleshed out the storage stuff yet. As such, I had no ID field on the object. The resolution was as simple as adding an ID field.
This resolves the problem, but does not in any way help me understand what went wrong.
For what it's worth, in the MVC project we use a custom user and role provider based on the ExtendedMembershipProvider, which uses a custom repository (that in turn uses the MembershipContext). The instantiation of the MembershipContext is identical between the test and the MVC projects. I can't imagine why they'd act differently.
It's as if something in the MVC project is forcing EF6 to read/validate every object in the Domain class to ensure their validity to a non-existing data model.
Does anyone have the slightest idea why this happened? I'm baffled, myself.

C# Dependency Injection with Unity, a unit of work, a database and the ability to change database at runtime

So I am wrestling with this for quite some time now, but I can't seem to figure it out.
At first I had a datalayer in my solution. This layer is for the communication between the business and the database. It had a generic repository and context objects so it is easy to retrieve and send data from and to the database with EntityFrameWork 6. This all worked very good... but...
Now I notice that in my application (WebAPI 2) I need to change database at runtime. This is really hard to do. It should follow this path:
An external application does a call to my API. In the header of the request is set which database should be used (an Id, or a logic name or whatever, not important now). Before an action is executed some code should read this header-item and set the new connection to the repositories.
This is how I register the repositories for Unity:
container.RegisterType<IContexts.ILanguageCodes<LanguageCode>, Data.LanguageCodes>();
container.RegisterType<IContexts.ISecurityRoles<SecurityRole>, Data.SecurityRoles>();
To show you everything what the implementations of these interfaces are is very much.
To change the connection to an other database I have to change the DBContext, which I know where to find, but the code doesn't. So I started Googling.
Then I found this article: http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/. I read it and all the stuff that is not good is in my project. I was like: Okay, lets start over on the datalayer.
THen I found this article: https://www.danylkoweb.com/Blog/a-better-entity-framework-unit-of-work-pattern-DD. I followed this and came pretty far. But got stuck on the part where the request comes in.
So basicly I am looking for this:
A way to change the connection to an other database at runtime with dependency injection, so I don't have to change the connection everywhere. In the end; the idea of DI is that you don't know where the implementation is, so in this case you don't know where all the connections are.
Does anybody have an example found on the internet I could use to try? Or maybe a good, small example I can focus on?
Long story, I hoped I could make it smaller. I hope someone can help me with this.
Thanks
When I need to support scenarios like this I have one "provisioning" or "configuration" database which holds the connectionstring for each customer/user/whatever. This is separate from the databases which map to the data my application needs.
Whenever the requests comes in you can configure your IOC container with the correct connectionstring, altough I don't know if unity supports this scenario, I know AutoFac / Ninject and most other containers allow changing the container.

IOwinContext context is null

I have moved my mvc4 application into mvc5 by creating a new application and copying the code in - to avoid any conflicts while updating the DLL's
When I debug my new solution, no pages can be loaded as the built in IdentityConfig.cs is throwing a nullreferenceexception on the IOwinContext.
the code is breaking at the following line
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
As this is practically OOTB mvc5, and I haven't worked with it before, I am not sure why it is throwing null.
any help?
I get that this is old, but I spent a while figuring it out,and I want to spare others the pain.
Make sure there is a Create() method in your DB context.
Make sure in Startup.Auth there is a line similar to: app.CreatePerOwinContext(ApplicationDbContext.Create);
Make sure (and this is critical) that last line is not commented out.
ok, this is an answer and probably a unique scenario. I actually had a dbcontext with exactly the same name as the one I wanted to use (it was legacy code) and I had actually added a Create statement to that same dbcontext by mistake...so, it was calling the wrong dbcontext and the wrong create method!
All sorted now though :-)

Basic EntityFramework Testing

I'm relatively new to EntityFramework and really want to get into testing things before I get too much further into things and have a huge codebase to retrospectively write tests for. I've not used it much and so methods are fairly basic, like below;
public Employee GetEmployee(int employeeID)
{
using (DatabaseContext db = new DatabaseContext())
{
return db.Employees.SingleOrDefault(e => e.idEmployee == employeeID);
}
}
This is fine in my app, but in my test project, it doesn't work because the test project doesn't seem to read the app.config file and so there's no connection string for DatabaseContext to use. I've read a bit about testing, nothing seems really definitive, though this post is the "official" way to do things (it's linked to from MSDN. The post seems fairly involved though and would require me to do things a lot differently than what I currently am, unless I've misunderstood some of it?
Could someone help clear this up for me? I can't even cheat and copy app.config across to the test project, it still doesn't read it (I've also tried renaming to MyApp.exe.config and still no luck). Is my GetEmployee method wrong? Should I do something more like the linked post? Or is there some way to test that I've not found yet?
#FizzBuzz - here is another article the discusses how to setup your unit test projects to work with entity framework:
How to get Entity Framework to read my app.config file in Unit Test project
You can read one approach for integration testing here.
About the config issue setting Copy to Output Directory property to Copy Always should do the work.
There are to options to resolve the issue you are facing.
Option 1: Create a mock for the app.config values. for mocking you can use Rhino Mock
Option 2: In your Unit Test project : Right click on the project > Add > Existing Item >
Select File > Add it as a link.
If you don't want to go with your live database (and right so!), then you basically have two options:
Use another database (must be of the same kind as your live db,
since EF doesn't allow for changing the db system, only its
location) and add another app.config to your unit test project
(which is the same as in your live project except that the db
connection string is different).
Use the NDbUnit framework, which
allows for defining the data in xml files. Here also you'll need an
individual app.config for your test project, if you don't want to hardcode the test data connection string. (This approach is only
advisable, if your live db has no or only very few schema changes,
because NDbUnit is quite allergic to these.) I wrote a blog post (with sample solution) about this approach here.
A third approach would be to mock all EF stuff, but this quickly gets overly complicated (you can find this also in a previous part of the above mentioned post, if you're interested).
HTH
Thomas
Thanks for the information people, found some interesting hints and tips through the various links supplied. In the end, I tried out this article from MSDN, funnily enough! Though it says it's for EF6, it does actually work for previous versions. The reason it indicates EF6 is for async stuff.

Categories