I have a class library I have been using for over a year that has recently stopped working after upgrading to EF 6.1.
I have tried various methods for passing in the connect string to my Context class constructor but while it seems to correctly pass the string I invariably receive:
'(((System.Data.Entity.DbContext)(context)).Database.Connection).ServerVersion' threw an exception of type 'System.InvalidOperationException'
and the connection state stays closed.
Here is my AppConfig:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
<connectionStrings>
<add name="MyContext" connectionString="Data Source=Server;Initial Catalog=DBName;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
My test class:
using System.Data.Entity;
namespace SVMIC.IMS.Entity.IMSClaim
{
public class Context:DbContext
{
static Context()
{
Database.SetInitializer<Context>(null);
}
public Context():base("MyContext")
{
}
}
}
and my test app:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SVMIC.IMS.Entity.IMSClaim;
namespace TestApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Context context = new Context();
}
}
}
The database server is SQL Server 2008 R2.
I assume it is something simple changed in 6.1 and I am just missing it, but I am totally stumped.
Ok, I have resolved the issue.
In frustration at not being able to fix the issue with 6.1, nothing I did made any difference to the result, and even building and stepping through the EF source accomplished little so I rolled back to EF 5.0 and rebuilt my code.
EF 5 immediately returned an error message identifying an issue in the schema definition, a view added by another developer that referenced system views was confusing my template, I fixed the issue and was back working in a matter of minutes.
The lesson learned here was, EF 6 needs some serious work on its error handling, as just returning a generic exception error left me chasing off in every direction, while the error message from EF 5 pointed me directly at the issue.
Based on the comments what appears to have happened is:
The original EF Upgrade did not work, so you were still running on the old EF
When you made the code change, the rebuild triggered that you would use the New EF
But the New EF dll's are not available, so you get the error.
Check you config: the EF Version is 6.0 not 6.1, also the Public key token is the same as for .net 2.0.
Just for information on this error
I was configuring Repository and Unit of Work Design Pattern with EF 6.1 with a simple test database named as "School"
It had following 3 tables
BookMaster
Library and
Student
I had created their respective Entity classes, Configurations classes, Repository classes and also created DB Sets in Entities class.
After few days I had created one more table whose above mentioned classes and DbSets were not created.
What I found is providing connectionstring name in base() constructor parameter was giving me following error
'(context.Database.Connection).ServerVersion' threw an exception of type >'System.InvalidOperationException' entity framework 6.1
However if I pass complete connection string as a parameter to base() method then it was working.
After some Trial and Error I deleted the 4th table that was created and It worked like a dream. So may be it is necessary to utilize all the tables and create the above mentioned classes and DbSets which may resolve this issue
If you are working local MDF file, the update the folder path of MDF file in App.config/ Web.config
else copy the dbmx App.cofig connectionStrings and paste to your project App.config/Web.config file.
Related
I am working on a older webservice, which uses Entity frameworks 6 to connect to Database.
The project is split up into web-service (controller) and "repository", which operated the database.
The idea is to now create an EXE which calls the repository, hence class library, which uses Entity framework. However, here I have some settings issues with connecting to the database.
The repository's config holds connection data, but for some reason it cannot connect.
Running is a default, hence default setting (none) of my exe, I get this error:
I can debug in into
public partial class My_TestEntities : DbContext
{
public My_TestEntities()
: base("name=My_TestEntities")
{
}
It crashes at that moment.
"Exception has been thrown by the target of an invocation." - which points to something deeper that just this.
I try to copy default into my own app.config
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="my_TestEntities" connectionString="metadata=res://..... stuff here..." />
</connectionStrings>
<appSettings />
This results in
"The type initializer for 'System.Data.Entity.Internal.AppConfig' threw an exception."
Copying the full config from the repository, some web stuff etc results in the same
Copying the configuration from the controller results in same as well.
I tried those things as I don't know what to do. I googled and found nothing.
So maybe here I can get some good ideas
I can answer this myself.
The parent exe calling the repository needs to have Entity framework (nuget package) installed, this will add some parts automatically to the config, as above.
Next, only the connection string is needed in the config file.
Then it works
I have started a WebAPI application using VS empty application template.
First, I have added the WebAPI service functionality - no issues.
Now, I need to add Entity Framework functionality, and I'm facing the following issue:
I do not have an App.config file in my application. Where can I put my database configuration parameters such as "Data Source=", "defaultConnectionFactory", etc...?
Currently, my ApplicationDbContext file looks like this:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebAPIService.Models
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext()
: base("DcToolDB")
{
}
public IDbSet<Site> Sites { get; set; }
public DbSet<Quote> Quotes { get; set; }
}
public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
base.Seed(context);
}
}
}
To give a more exact answer to this question: you have to include the configuration file (app.config or web.config) in the project that will be executed, and not in any other class library project. If the configuration file doesn't exist, create one. You can do it easily in VS by adding a new item of type "Configuration file" in the chosen project. It will create a web.config file or an app.config depending on the kind of project.
What does "the project that will be executed" mean?
When it's a desktop application or a web site, it's very clear. But, if you have a test project, that will be the executable project qhen you run the tests. So, if you have for example a web application with a two different test projects, you need 3 config files:
web.config in the web app project, which sill be used when running the app
one app.config for each test project, which will be used when you run the corresponding tests
This is interesting, beacuse it allows to keep different configurations for each project.
I did have App.config after all, just did not see it at first.
Once located, I have added a section for Entity Framework:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="Data Source=.\SQLEXPRESS2012; Initial Catalog=DcToolDB; Integrated Security=True; MultipleActiveResultSets=True" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
and was able to accomplish the desired result.
I'm playing around with EF different workflows. Yesterday I made a new project and Entity Framework 6 was the first suggestion from Nuget so I decided to give it a try, also it is a very small project entirely for learning purposes so I guess it will be good experience to try EF 6 since I've been working mostly with Ef 5.
My Application is based on Code First approach. The structure of the solution is shown in the print screen:
The project CodeFirstClasses is meant to hold my Entites. For simplicity purposes and because I follow a tutorial I use only one class as you may see - Customer.cs. There I have :
public class RewardContext : DbContext
{
//Specify the name of the base as Rewards
public RewardContext() : base("Rewards")
{
}
//Create a database set for each data item
public DbSet<Purchase> Purchases { get; set; }
public DbSet<Customer> Customers { get; set; }
}
And the other classes - Purchase and Customer which are trivial, so I won't paste them here.
The other project as you can see is Windows Forms project with just one form and button on it. On the click event of the button I have all the logic for adding new records to my two entities hardcoded. Here is just a part of it:
//some code...
//Add the record and save it
context.Customers.Add(newCustomer);
context.Purchases.Add(newPurchase);
context.SaveChanges();
MessageBox.Show("Record Added!");
So far nothing different from what I'm used to with EF 5. I can build the project, I can run it, and everything is executed as expected. However I get this warning from the title :
Warning 1 The element 'entityFramework' has invalid child element 'providers'. List of possible elements expected: 'contexts'. And even though I'm using mostly MS SQL Server Management Studio I've noticed that I'm not able to manage my connections/databases from the IDE - Visual Studio 2012, but this was not an issue with EF 5.
My research narrowed down the possible source of problem/solution to manually changing the App.config file, but this is an area where I haven't got much experience especially when the IDE took care of it until EF 6. So I'll post both my App.config files for this solution :
The one from the CodeFirstClasses project :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
And from my TestCodeFirst project:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
And the other possible solution that I found is : updating the xsd for "validating" EF config section in web/app.config file to recognize newly added EF6 elements which I'm also not aware of how exactly to do it.
Even though when I open the MS SQL Server Management Studio I see the database created for this application, the records are saved and generally it seems to work but yet I would like to resolve this warning and get to know how to set up my applications based on EF 6 right.
You can install the EF6 Designer for VS2012 from here and it will update the schema that validates config files.
The configuration schema was changed from version 5 to 6. As it says, the providers node was replaced with a contexts node.
The idea is that you can configure the providers individually instead of all contexts using the same provider. (This goes in tandem with being able to have multiple contexts that reside within one database. This used to be called multi-tenant but was later renamed to be more concise)
Up to EF5, in order to connect to SQL Server 2012, all I needed to to is specify a connection string that looks something like this:
Data Source=.\SqlExpress;Initial Catalog=MyDatabase;Integrated security=True;MultipleActiveResultSets=True
This method is not working with EF6, giving exception
No Entity Framework provider found for 'System.Data.Odbc' ADO.NET provider. Make sure the provider is registered in the 'entityFramework' section of the application config file
I am not using app.config file at all, I am passing above connection string to MyContext constructor. WHy is it trying to use Odbc provider at all, and instead not using System.Data.SqlClient?
What needs to be done to connect to SQL Server with EF6 code-first? I made sure that EntityFramework.dll and EntityFramework.SqlServer.dll are both available in Application folder. I have even added EF6 nuget package v6.0.0.1 in WPF project, although it does not use EF library directly, and making sure that automatically created App.Config file (by nuget) is copied to Application (Debug) folder - still no success.
I have also tried to setprovider manually in code:
public class OeeCoachConfiguration : DbConfiguration
{
public OeeCoachConfiguration()
{
SetProviderServices("System.Data.SqlClient",
System.Data.Entity.SqlServer.SqlProviderServices.Instance);
}
}
Still no success. My Project structure is as follows (simplified):
WPF project - does not have reference to EF (also tried adding EF reference)
ViewModel class library - does not have reference to EF
Model class library - has reference to EF library (both dlls)
Data class library - has reference to UI library (both dlls).
I am using CodeFirst approach, and this setup works without any problem with EF5. Any help is greatly appreciated.
For me this error was resolved by removing the Glimpse.ADO package
Edit December 20, 2013 I believe the Glimpse.ADO package now supports EF6, but I have not tested it.
I had the same problem and I eventually tried the following and it worked (keeping Glimpse EF5 & Glimpse ADO packages)
In the web.config I added a copy of the existing provider line but changed it's invariantName to "System.Data.Odbc".
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.Odbc" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Hope that this helps.
Jonathan
Yes, for me it was resolved by removing Glimpse.ADO and Glimpse.EF5 nuget packages. Thank you.
Option 1: Try adding following in app.config of the executable project.
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Option 2: If you want to use code based provider registration, follow guideline on Entity Framework Providers for EF6
Make sure you have the DbConfiguration in the same assembly as the DbContext of your application.
Right now, in development I have the following code in the Global.asax.cs file that calls the Entity Framework (v4.1) SetInitializer with my SeedSampleData method. This all works perfectly.
However, I would like to store the SetInitializer "strategy" parameter through a web.config setting so that I can create a deployement script that will automatically set it to new System.Data.Entity.CreateDatabaseIfNotExists<EfDbContext>() instead of my seed method during production deployment.
The reason for wanting to move this to the web.config is that when I roll out a new deployment to the production server I want to make sure that I don't accidentally leave my seed initializer in the code.
protected void Application_Start()
{
//TODO: Figure out how to move the following lines to web.config and have a deployment script modify it when going to production.
//This line is for production
//System.Data.Entity.Database.SetInitializer(new System.Data.Entity.CreateDatabaseIfNotExists<EfDbContext>());
//This line is for development
System.Data.Entity.Database.SetInitializer(new Domain.Concrete.SeedSampleData());
//... Remainder of Application_Start calls here...
}
If you update to EF 4.3 (which is a good idea anyway), then you can use something like this in your web config:
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<entityFramework>
<contexts>
<context type=" Blogging.BlogContext, MyAssembly">
<databaseInitializer type="Blogging.MyCustomBlogInitializer, MyAssembly" />
</context>
</contexts>
</entityFramework>
</configuration>
Rowan wrote about it in detail here: http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-configuration-file-settings.aspx
If you really want to keep using 4.1, then there is an older syntax that you can use instead. I wrote about it here: http://blog.oneunicorn.com/2011/03/31/configuring-database-initializers-in-a-config-file/
If I understand correctly, your SeedSampleData initializer is used only for debug purposes?
I don't know if there is a config parameter to control this, but you can use preprocessor directives:
#if DEBUG
System.Data.Entity.Database.SetInitializer(new Domain.Concrete.SeedSampleData());
#else
System.Data.Entity.Database.SetInitializer(new System.Data.Entity.CreateDatabaseIfNotExists<EfDbContext>();
#endif
(assuming, of course, that you don't deploy debug assemblies in production...)