where to put Entity Framework configuration strings in a WebAPI application - entity-framework

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.

Related

Executing EFcore Migrations inside a .NETStandard Library project

My question is basically: is it possible to use Entity Framework Core (and migrations) inside a .NET Standard 2.0 library project? (not a core project)
I currently have 2 projects:
ASP.NET Core main project: I don't want anything with databases or EF inside this project, so I added a reference to the .NETstandard2.0 DAL project
.NETStandard2.0 data access layer project: EF Core with database migrations project for accessing the database. The main project uses this project to get data from the database.
For the .NETStandard DAL project, I use the following settings and classes: the .csproj file contains the dependencies for EF and migrations:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>
After calling dotnet restore, I created a DbContext descendant:
class MyTestContext: DbContext
{
public MyTestContext(DbContextOptions<MyTestContext> options) : base(options)
{
}
public DbSet<Class1> Class1Table { get; set; }
}
And added a DbContextFactory with IDesignTimeDbContextFactory like:
class DbContextFactory : IDesignTimeDbContextFactory<MyTestContext>
{
public MyTestContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<MyTestContext>();
builder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=efmigrations2017;Trusted_Connection=True;MultipleActiveResultSets=true",
optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(MyTestContext).GetTypeInfo().Assembly.GetName().Name));
return new MyTestContext(builder.Options);
}
}
Okay, so far everything works fine and the .NETStandard project builds successfully.
Now I want to create my first migration by executing:
dotnet ef migrations add InitialCreate
This throws an error:
If I understand the error message correctly, EF Core can only be used in .NET Core and .NET Framework projects and NOT in .NETStandard projects?
If that is true, how can I separate the EF database logic from my other applications?
If not, how can I get the migrations to work?
Thank you in advance
You have two options.
One: Use your ASP.NET Core project as the startup project.
dotnet ef migrations add InitialCreate --startup-project ..\MyWebApplication
Two: Cross-target .NET Core in your class library. (Edit the *.csproj)
<PropertyGroup>
<!-- Note: This property name becomes plural. -->
<TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>

EntityFramework 6.1 cannot connect

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.

How to resolve Warning : The element 'entityFramework' has invalid child element 'providers'. List of possible elements expected: 'contexts'

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)

Connecting to SQL Server with EF6

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.

Running WatiN tests with Nunit error?

When I try to run a WatIn test trough the NUnit ide, I get the error message:
ConsoleApplication1.Tests.CanBrowseToMicrosoft:
System.Threading.ThreadStateException : The CurrentThread needs to have it's ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer.
I created an application configuration file called ConsoleApplication1.exe.config which is below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="NUnit">
<section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>
<NUnit>
<TestRunner>
<add key="ApartmentState" value="STA" />
</TestRunner>
</NUnit>
</configuration>
My class Tests.cs is below:
[TestFixture]
public class Tests
{
[Test]
public void CanBrowseToMicrosoft()
{
using (var browser = new IE())
{
browser.GoTo("http://www.microsoft.com/");
Assert.That("Microsoft Corporation", Is.EqualTo(browser.Title));
}
}
}
Am I doing something wrong?
The other question I had was how do I get the NUnit test results to show up in vs2008 ide instead of having to run the NUnit Gui?
I figured it out, because I was loading an NUnit project called Tests.nunit, I need to call the application configuration file Tests.config. After this change, it worked fine.
There is a cleaner way to resolve your issue with STAThread requirement, but it requires NUnit 2.5.
Also, have you tried TestDriven.Net to run unit tests from Visual Studio?