I have one issue I am trying to resolve for days now, but I can’t get the right approach.
I am using EF4 and I have one application where I use DataBase First, which originally created the ObjectContext, and I donwloaded the DbContext generator and generated it.
The thing is, I need the application to be able to get the database SCHEMA from some configuration file, instead of ALWAYS using the “dbo” default.
I was trying to use the “ToTable” method (so I can specify the schema) in the “OnModelCreating” overload method but as this article sais, as I am using DataBase First, that method is not called.
How can I make the schema name configurable?
Is that even possible?
I read this article too, where it says I can combine database first with code first but I can’t see how to do that if I can’t use the "OnModelCreating" method.
Thanks a lot in advance!!!
I don't know about configuring schema. However if you want your db first approach to changed to the code first, just change the string parameter of your DbContext constructor.
Suppose that you have the following DbContext that EF Db first created for you:
public class MyDbContext : DbContext
{
public MyDbContext()
: base("Name=DefaultConnection")
{
}
// DbSets ...
}
change that to the following to start using code first and all magic tools of it (migration, etc.):
public class MyDbContext : DbContext
{
public MyDbContext()
: base("YourDbFileName")
{
}
// DbSets ...
}
It causes that EF creates a new connection string using SQL Express on your local machine in your web.config file with the name YourDbFileName, something just like the early DefaultConnection Db first created.
All you may need to continue your way, is that edit the YourDbFileName ConStr according to your server and other options.
Related
I would like to pass a connection string to the constructor of DbContext. The way to do this has been answered here: Pass connection string to code-first DbContext
(code if you don't like to click)
public MyContext(string connString)
: base(connString)
{
}
However, when I attempt to enable migrations I receive the error: "The target context '...' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory."
Also, when I attempt to use EF PowerTools to generate an Entity Data Model is receive the error: "A constructible type deriving from DbContext could not be found in the selected file."
Is this a common problem? I have a fix, but it feels like a hack. Any one else have to deal with this before?
Add also an empty constructor, e.g...
public MyContext()
{
}
Thing is once you define a parametrized ctor your default one gets hidden
e.g. see Why does the default parameterless constructor go away when you create one with parameters
That's also one way of 'hiding' default construction from the outside users.
Usually you don't even expose that 'other' ctor to the outside - as its 'yours', you just hardcode inside what you need. Or alternatively and better - you use the 'app.config' to specify the connection string. For details (and problems with it) see...
Migration does not alter my table
Migration not working as I wish... Asp.net EntityFramework
I want to inject a custom connection string into my EF context instead of using the connection string in my web.config. The idea is to move all database related logic off of my MVC project into a separate layer. I also want this layer to be responsible for the proper connection strings instead of my web applications.
The services currently using the context are calling the default constructor:
using (var context = new MyDbContext()) {
//...
}
The default constructor is internally calling DbContext with the name of the connection string from the web.config:
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyDbContext")
{
}
//...
}
In order to inject my custom connection string I would need an overloaded constructor which takes the connection string as an argument. Unfortunately there is not such a constructor provided.
It is obvious that adding the constructor overload manually right inside the MyDbContext class would be a very bad idea, since this class is auto-generated and will be overwritten any time soon. Let's not talk about this any more, it's forbidden. Period.
Since MyDbContext is a partial class, one could add the additional constructor in a separate class file partial class MyDbContext, but this seems smelly either. I don't know why, but my brain says bad idea.
After some investigation I found out, that one can tell EF to include this additional constructor by editing the T4 template Model.Context.tt which is a mix of C# and some template markup. Here is the original constructor:
public <#=Code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
WriteLazyLoadingEnabled(container);
#>
}
It is obviously easy to add similar logic to generate an overloaded constructor containing the connection string:
public <#=Code.Escape(container)#>(string nameOrConnectionString)
: base(nameOrConnectionString)
{
<#
WriteLazyLoadingEnabled(container);
#>
}
I tried this and noticed, that both re-generating the model classes and updating the model from DB will not affect the T4 template, thus the additional constructor will always be there. Good! At first glance this looks like a suitable solution, but...
And here is my question: Is that really a good solution?
Let's compare the three options again:
Edit the auto-generated class (ok, we agreed to forget about this)
Add the constructor in a partial class file
Edit the T4 template to tell EF to generate the additional constructor
From these three options the third seems to me to be the most convenient and clean solution. What is your opinion? Has someone a good reason, why this would be a bad idea? Are there more options to inject connection strings, maybe using a custom connectionFactory? If so, how would I do that?
Like #shaft proposed, I replaced my T4 template approach to using a partial class. As it turned out, this is indeed a lot simpler and intuitive, than any other solution I currently know of.
The auto-generated class looks like:
public partial class MyDbContext : DbContext
{
public MyDbContext() : base("name=MyDbContext")
{
}
//...
}
I just added another partial class of the same name. Issue solved.
public partial class MyDbContext
{
public MyDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
}
From the 3 options you provide I'd rather choose option 2. Hasn't the partial keyword been introduced to solve the problem with autogenerated files? Using T4 templates brings additional complexity in my opinion, the maintaining developer has than to understand one more thing (Not everyone is familiar with T4), but extending a partial class is more standard c# development.
However I don't know the answer to 'is there a really good solution". Introducing a factory brings again new code to maintain, test and to understand, I am not sure this abstraction helps here because the factory itself would need to instantiate the dbcontext with the appropriate constructor (which you have to provide anyway).
Edit:
Just thought about it once more: the factory might be useful to resolve the connection string from another location (you said that you don't want the connectionstring in web.config), but that still doesn't solve the constructor problem
I am an ASP MVC 3 noobie who has done a few tutorials. Now I'm trying to build a site. All of the tutorials on the microsoft website emphasize the code-first approach: you define your model with code and then create a datacontext and then the entity framework creates/manages the DB based on your code.
I set up an Employees class and a DataBaseContext class that inherits from DbContext. I added a connection string to Web.config connection string that successfully links DataBaseContext to an already existing empty DB on SQL server. EDIT= That was the problem. See my answer below
But when I try to run the Employees controller created thru scaffolding, I get this error
Invalid object name 'dbo.Employees'.
Description: An unhandled exception occurred during the execution of...
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.Employees'.
I followed this post SqlException (0x80131904): Invalid object name 'dbo.Categories' and realized that if I create an employees table on the DB, this excpetion goes away (I get a new one saying that the column names are invalid).
But I thought the whole point of MVC 3 is that the framework will make the DB for you based on the code.
Maybe I need a line of code in the Global.asax Application_start() to create the database? Here is my application_start method:
Sub Application_Start()
AreaRegistration.RegisterAllAreas()
RegisterGlobalFilters(GlobalFilters.Filters)
RegisterRoutes(RouteTable.Routes)
End Sub
Here is the code for Employee:
Public Class Employee
Property EmployeeID As Integer
Property First As String
Property Last As String
Property StartDate As DateTime
Property VacationHours As Integer
Property DateOfBirth As DateTime 'in case two employees have the same name
End Class
Here is the code for the DB context:
Imports System.Data.Entity
Public Class DatabaseContext
Inherits DbContext
Public Property Employee As DbSet(Of Employee)
Public Property AnnualLeave As DbSet(Of AnnualLeave)
End Class
What am I missing?
By default EF uses DropCreateDatabaseIfModelChanges<TContext> database initializer. Accordingly to the MSDN:
An implementation of IDatabaseInitializer<TContext> that will delete, recreate, and optionally re-seed the database with data only if the model has changed since the database was created. This is achieved by writing a hash of the store model to the database when it is created and then comparing that hash with one generated from the current model.
Since the database was created manually, EF can't find the hash and decides do not perform any further initialization logic.
You might want to look into this article, same question successfully answered already.
Or it can be this (also resolved successfully)
Answer to your problem is most likely one of the two.
Hope this will help you
Does the name you're specifying for your connection string match the name of your database context?
For example:
Context
var myDbContext = new MyDbContext();
Connection string
<connectionStrings>
<add name="MyDbContext" connectionString="YOUR.CONNECTION.STRING" providerName="System.Data.SqlServer" />
</connectionStrings>
Try and see if this post I wrote about DbContext with MVC works for you: Code-First
Not a lot to be done to get this to work, but there are a few things that are easily missed that will cause a bunch of head aches.
hope this helps
I had already created a database with that name on SQL server. Once I deleted the existing database, the code first framework created the tables for me like it was supposed to. It seems like if the database already exists, the framework won't set up the tables for you. It wants to create the whole DB from scratch.
You were using AdventureWorks Database?
It has it's own schema assigned to the employees table. HumanResources.Employees and not the default dbo.Employees.
Even though I've identified the problem, I don't know the solution to using the database as configured with the HumanResources schema.
Anybody know?
I have a small asp.net mvc4 application (working fine in my local machine), that uses entity framework v4.1.0.0 with ADO.net DbContext Generator.(SQL Server 2008 r2)
I am adding newer versions of dlls required through the "Add Deployable Dependencies..." context menu in Visual Studio 2010.
I have a shared hosting with godaddy.com, I have uploaded the files to server and created the database, now here comes the problem.When I try to browse my site I get the following error:
CREATE DATABASE permission denied in database 'master'.
I looked this up around and found out that this error was caused by EF code first trying to create database.but i do not want EF code first to recreate the database, how do i turn off this automatic database creation altogether? I have no intentions of using the code-first feature whatsoever.
Please help.
put this code into the Application_Start() method of Global.asax or constructor on your DbContext class
Database.SetInitializer<MyContext>(null);
If you want to recreate database when POCO domains are changed, use following code instead of above
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
If you are using EF Migrations, this is what you set for it:
public sealed class DbConfiguration : DbMigrationsConfiguration<DatabaseContext>
{
public DbConfiguration()
{
AutomaticMigrationsEnabled = false;
}
}
But this doesn't answer the question on EF Code First itself. If the database already exists, then EF will not try to create it. So you just need to point it to an existing database. And to make sure the connection string name is the same as the name of the database context. If it is not, you need to provide it to it with some overrides:
public class DatabaseContext : DbContext
{
public DatabaseContext()
: base(ApplicationParameters.ConnectionStringName)
{
}
public DatabaseContext(string connectionStringName)
: base(connectionStringName)
{
}
}
I was creating an mvc application and i had a model class with a dbcontext function the variables were in the same file. I added another field and changed the code in the edit create delete details and index views but i now get an error saying
"The model backing the 'GameDBContext' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data."
Imports System.Data.Entity
Public Class Game
Public Property ID() As Integer
Public Property Name() As String
Public Property Genre() As String
Public Property Price() As Decimal
Public Property Developer() As String
End Class
Public Class GameDBContext
Inherits DbContext
Public Property Games() As DbSet(Of Game)
End Class
you need to add a initializer method to the Application_Start method in Global.asax file. Ex:-
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<GameDBContext>());
Since it sounds like you're using a code first approach in developing your application, here are a couple of links that might help you:
code first development with entity framework 4
Code First/Entity Framework 4.1 Videos and Articles on MSDN
All of these can give you a better understanding of what is happening and how to work around having your database change on you.
In short, since you added another property, the entity framework table in your database is now longer in sync with your class. Since it's no longer in sync, you must manually delete this database in order to regenerate it, or you must create an initialization for the database. All of these concepts are better described in the links I have provided.
Good luck, and hope these help you some.