I'm using the Model First approach with EF6 and I'm trying to use Entity Framework Effort to develop in-memory tests.
Here is what I do in my test:
var inMemoryConnection = Effort.DbConnectionFactory.CreateTransient("name=MyEntities");
var inMemoryContext = new MyEntities(inMemoryConnection);
MyEntities:
public partial class MyEntities: DbContext
{
public MyEntities(DbConnection dbConnection)
: base(dbConnection, contextOwnsConnection: true)
{
}
When I run the tests, I get an error saying I didn't specify any [key] attributes which is normal since I am not using a Code First approach. Therefor, the OnModelCreating method is called and shouldn't have to.
Is there a way to use Effort in a Model First design without having to add these attributes?
Thanks !
I found my mistake.
Turns out Effort.DbConnectionFactory.CreateTransient is used for Code-First.
Instead if you're working with a .edmx, Model-First, it is Effort.EntityConnectionFactory.CreateTransient("name=MyEntities") you have to use.
I too had a bit of a difficult time in trying to get Effort to work with a DB first, or model first as it's also known, approach. This is what I did to make it work:
Download the Effort.EF6 nuget package
Add the effort.provider to the entity-framework config section:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="Effort.Provider" type="Effort.Provider.EffortProviderServices,Effort" />
</providers>
</entityFramework>
Replace the sql-provider with the Effort-provider in the connection-string:
<connectionStrings>
<add name="testDb" providerName="Effort.Provider" connectionString="metadata=res://*/StaginDB.csdl|res://*/StaginDB.ssdl|res://*/StaginDB.msl;provider=System.Data.SqlClient;provider connection string="data source=testDB;initial catalog=foobaroo;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" />
</connectionStrings>
If your model-first context doesn't offer a constructor you can inject a connection into, you can modify your tt-template to do so:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
// I added this constructor so I could inject a db-connection into the context:
public <#=code.Escape(container)#>(System.Data.Common.DbConnection dbConnection, bool contextOwnsConnection)
: base(dbConnection, contextOwnsConnection)
{
}
// Original constructor
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoa.... etc. etc.
And we can now use that constructor to instantiate a connection, and an Effort-based in-memory db-context based on this connection:
System.Data.Common.DbConnection connection = Effort.EntityConnectionFactory.CreateTransient("name=KPDBSTAGINGEntities");
TestDbContext testDbContext = new testDbContext(connection, false);
TestDbContext.your-entity.add( new your-entity() { etc. tec. });
TestDbContext.SaveChanges();
Hope this helps.
P.S. Others have had to add a db-provider-factory section to their config. This was not required for me, but maybe for you:
<system.data>
<DbProviderFactories>
<add name="Effort.Provider" invariant="Effort.Provider" description="Effort.Provider" type="Effort.Provider.EffortProviderFactory,Effort" />
</DbProviderFactories>
</system.data>
Related
I'm trying to use a MySQL database with asp.net MVC via a code first approach and I don't know how to create the tables, I thought it would create by itself.
I get the message : "Table 'XXX.aspnetusers' doesn't exist"
Do I need to run migrations or something like that?
Thanks
I got a little further by using update-database. You must have change your connection string and your provider to correspond to your MySql
Example :
<add name="DefaultConnection" connectionString="server=127.0.0.1;User Id=root;password=;database=myDB" providerName="MySql.Data.MySqlClient" />
Provider :
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>
</providers>
</entityFramework>
You should also put this on your dbContext :
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
Thanks
I'm trying to port my MVC 5 application to MVC 6. I'm using Devart dotConnect for MySql and Oracle. I have trouble configuring my application.
Right now I have the following entries:
<entityFramework>
<providers>
<provider invariantName="Devart.Data.MySql" type="Devart.Data.MySql.Entity.MySqlEntityProviderServices, Devart.Data.MySql.Entity" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Devart.Data.MySql" />
<add name="dotConnect for MySQL" invariant="Devart.Data.MySql" description="Devart dotConnect for MySQL" type="Devart.Data.MySql.MySqlProviderFactory, Devart.Data.MySql" />
</DbProviderFactories>
</system.data>
My application have 3 DbContext classes (2x MySql, 1x Oracle) in separate assemblies, and I can only have 1 DbConfiguration class (Entity Framework 6 limitation).
If I set this configuration other contexts complain that they cannot see assembly with DbConfiguration class.
How do I get over that limitation?
I found myself in a similar situation the other day, and had to rely on web.config to enrich the configuration
<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly">
...Your EF config...
</entityFramework>
Edit
The second option is to place DbConfigurationTypeAttribute on your context class
[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}
For more details check these resources
Ef6 docs: Code-Based Configuration Type (EF6 Onwards)
Ef6 docs: Moving DbConfiguration
I had migrations enabled - however, now I'm moving to the live server, it appears migrations are still trying to update the database, as I get the error:
CREATE TABLE permission denied in database 'secn'.
I have this in a context file in my models folder:
namespace lhts2.Models
{
public class DefaultConnection : DbContext
{
public DefaultConnection() : base("name=DefaultConnection")
{
Database.SetInitializer<DefaultConnection>(null);
}
}
}
...and in my web.config file, my connection string is:
<add name="DefaultConnection" connectionString="Data Source=[servername];
Initial Catalog=secn; Integrated Security=True;" providerName="System.Data.SqlClient" />
I have deleted the Migrations folder too, and republished - but still I get the error above.
I also have this in my web.config file:
<configuration>
<configSections>
<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>
Do I need to set the SetInitializer in some other place, other than in the context file in my models folder?
Thanks for any advice,
Mark
From here:
...the initializer should have been set in the static constructor of your context. The static constructor is called before any constructors and is executed once. This is what we want. The reason is that in some of your application, you may initialize more than once the context. You do not want to execute all the process to check if the database if ready to be changed or not.
So, you should change your class to have a static constructor that is only called one time.
namespace lhts2.Models
{
public class DefaultConnection : DbContext
{
static DefaultConnection()
{
Database.SetInitializer<DefaultConnection>(null);
}
public DefaultConnection() : base("name=DefaultConnection")
{
}
}
}
I had the same issue. Setting the IIS user to a "sysad" level user allowed the application to work normally. However that is not a secure method of solving the problem.
Further research revealed that the "migrations" table (named dbo.__MigrationHistory) was the culprit. I had given the IIS user access (Select, Update, Delete, Insert, and References) to all the "application" tables, but not the "migrations" table. Consequently when the application runs and attempts to determine if a migration is necessary, the access fails because of the lack of access rights for that user and the application thinks it needs to create the database and tables - which this user clearly should not have rights to do.
By providing normal access rights to the __MigrationHistory table (Select, Update, Delete, Insert, and References) the IIS user was now able to determine that no migration was necessary and therefore did not attempt to conduct a migration.
Example of Permission Settings Here
I am using Entity Framework 6 in a ASP.NET MVC application. I am using a Code First approach to try and connect to an existing database.
Firstly, I have set up a Model as follows:
public class Employee
{
public int ID { get; set; }
public string PAYCODE { get; set; }
}
Secondly, I have a Context as follows:
public class EmployeeContext : DbContext
{
public EmployeeContext()
: base("EmployeeDB")
{
}
public DbSet<Employee> Employees { get; set; }
}
Thirdly, I have specified the connection to the DB in the web.config:
<connectionStrings>
<add name="EmployeeDB" connectionString="Server=MyServer;Database=MyDB;User ID=MyUserID;Password=MyPassword;Trusted_Connection=False" providerName="System.Data.SqlClient" />
</connectionStrings>
Finally, I call my context from a Controller class as follows:
var db = new EmployeeContext();
However, this throws the following run-time error:
The Entity Framework provider type 'System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' did not have a static property or field named 'Instance'. Entity Framework providers must declare a static property or field named 'Instance' that returns the singleton instance of the provider.
I would be extremely grateful if anyone can shed some light on this error - I have tried searching on the Web, and have followed Microsoft examples.
Many thanks!
Martin
Added in response to question below:
The following is at the foot of my web.config:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="System.Data.OracleClient" type="System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</providers>
I have found out that the error message was caused by trying to use 'System.Data.OracleClient' as a provider for EF6.
It looks to me that this provider cannot be used to connect to Oracle from an EF6 application.
After some searching, I am trying to replace the provider with Devart dotConnect, but the version that my company owns seems to be too out of date to support EF6.
There doesn't seem to be many resources to help with connecting EF6 to Oracle.
Looks like you need to change your connection factory to SqlConnectionFactory. http://blogs.msdn.com/b/davidobando/archive/2012/08/14/changing-ef-s-default-provider-from-localdb-to-sql-server.aspx
I have created a project call Repository.EF to handle Data access in a n-tire solution. I have added EF to the Repository.EF project where I have all my POCO's . Then I created a DbContext class in that project like this.
namespace LearningSpike.Repositories.EF
{
class GlassContractDbContext:DbContext
{
public GlassContractDbContext() : base("GlassContractContext")
{
}
public DbSet<MetalStock> MetalStock { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new MetalStockConfiguration());
}
}
Then went to package manager console and did
Enable-Migrations
Then set the
AutomaticMigrationsEnabled = true;
Then
Update-Database
Everything is working fine. But the problem is, I don't know where the connection string is. It seems like there is no connectionString in that particular project. I know if I had an MVC4/5 template, there will be a connectionString in the web.config. How can I find the connection string?
How do I configure things now? For example I remember doing this with the connectionString in a MVC5 app
MultipleActiveResultSets=true
How do I do it now?
Thanks!
Cheers!
PS
Also I have the following code in my App.config in the Repository.EF Project
<?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>
<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>
When running the package manager console it will default to use the start-up project (unless you specify the -project param in the command or use the drop down in console manager). From there it will look for your connection strings in the config files of that project. If that is a web project this will be in the web.config.
If you have not added your own connection string to that project, EF will be able to use its own one derived from the project name and create an mdf file which it attaches on the fly during runtime.
If you want to add a connection string (you can do this is any of your config files - however by the sounds of it you want to add this to the app.config in your datalayer project) you can add this below your config sections:
<connectionStrings>
<add name="MyDatabase"
providerName="System.Data.SqlClient"
connectionString="Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"/>
</connectionStrings>