Understanding VS's ability to create database on first run - asp.net-mvc

I'm working with a (.net4 / mvc3 ) solution file downloaded (from a reputable source) where a connection string exists in web.config but I don't see explicit instructions to create the database and there's no included '.mdf'. The first time I build I got a runtime error regarding lack of permissions to CREATE database. So I created a blank db and made sure the string referenced a SQL user that had .dbo/owner rights to the db just created.
But subsequent builds don't seem to execute that same initialize db script - where ever that's stored.
Where is this 'first use' convention for creating databases documented?
thx

That is a feature of Entity Framework Code First. I am not sure what you are looking for exactly, but searching for "EF Code First Initialization Strategy" might help.
For instance read this article: EF Code First DB Initialization Using Web.Config

I assume you are talking about Entity Framework, which allows you to create the database from an instance of an ObjectContext object, which is used in any of the three approaches in EF (database-, model- and code-first).
Look for a line that actually calls ObjectContext.CreateDatabase(). If one of the supported ADO.NET provides is used (SQL Server or SQL Server CE 4.0) this will generate the required SQL Statements. Assuming the classic Northwind example, you might find something like that:
NorthwindContext context = new NorthwindContext();
if (!context.DatabaseExists())
{
context.CreateDatabase();
}
If this is in fact a code-first application, "lalibi" is right about the initialization strategy which by default doesn't require you to explicitly create the database. (But my guess is, that it actually uses a statement internally very similar to mine).

Related

How to update a database schema in Spring4D 1.2

I'm experimenting with Spring4D 1.2's simple ORM (Marshmallow). I could get it to work pretty well but I can't find out how to have it update an existing database with a new schema.
For instance, in the "GettingStarted" project, I added one property to the data model:
[Entity]
[Table('Products')]
TProduct = class
{...}
[ColumnAttribute('PRODUCTINFO',50)]
property Info: string read fInfo write fInfo;
No matter what, I can't get the framework to update the schema if the database already exists.
What am I missing ? Must I do that manually outside the framework ?
Schema update is currently not supported nor planned from my side.
Generating the necessary drops and recreate would be reasonably easy but that is only part of the story as you probably want to keep any existing data. From using SQL Server Data Tools I know how deep this rabbit hole can go.

New project fails using WebAPI and Breeze

I receive the following error when trying to run the new project per the instruction in the Readme file.
1: querying Todos
2: Query failed: The action 'Todos' on controller 'BreezeSample' with return type 'System.Collections.Generic.List`1[[MyTasks.Api.Models.BreezeSampleTodoItem, MyTasks.Api, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' cannot support querying. Ensure the type of the returned content is IEnumerable, IQueryable, or a generic form of either interface.
UPDATE:
I checked my event viewer, and see a SQL error that I've never seen before when trying to debug on my machine -
Login failed for user 'my-machine\user-name'. Reason: Failed to open the explicitly specified database. [CLIENT: ]
It seems that the database being generated by BreezeSamplesContext is inaccessible for some reason? It has been generated by code-first, but I can't query it (apparently).
UPDATE 2:
I've changed the default method to -
[HttpGet]
public IQueryable<BreezeSampleTodoItem> Todos()
{
System.Data.Entity.DbSet<BreezeSampleTodoItem> result = null;
try
{
result = _contextProvider.Context.Todos;
}
catch (Exception exc)
{
throw new Exception(exc.Message);
}
return result;
}
Although the Seed method works, and the database is dropped and repopulated with seed values, I get a response of 0 items in the 'result' above.
UPDATE: December 15
The critical piece of information ... the reason for the problem ... is the use of the pre-release SPA template.
That template is not the same as the MVC 4 Web API or Empty templates that are described in the Breeze documentation
The SPA Template and the MVC update include the beginnings of ASP.NET Web API support for OData queries. Their stab at OData conflicts with Breeze; the two forces are wrestling for ownership of the OData query. Wish we could use theirs but it is missing essential features such as support for $select and $expand.
Fortunately, it is easy to disable the MS version so that Breeze prevails. Open App_Start/WebApiConfig.cs file and delete or comment out the following:
config.EnableQuerySupport(); // conflicts with Breeze's ODataActionFilter
The misleading error about "return type" should disappear and you should be back in business.
Note that taking this step turns off the MS Web API OData filter for the entire site. We have it on our backlog to update the Breeze ODataActionFilterAttribute so that it disables the MS Web API OData handling for the Breeze controller only. We hadn't bothered yet because the SPA template remains unofficial at this time. For the nonce ... you can't mix Breeze and Web API OData queries in the same site ... unless you're prepared to do the per-controller filter cleanup yourself.
We have a Breeze version of the new SPA Template working and almost ready to release. I'll be writing about it shortly and will update this answer with a link.
Below is my previous answer which I preserve mostly because (a) it describes how to diagnose a problem and (b) is the context for the comment chain.
Let's start over and see if we can diagnose. Close all Visual Studio sessions (that should stop IIS Express). Launch a fresh VS session. Create an MVC4 Web Api application in VS 2012. Add the Breeze.MVC4WebApiClientSample NuGet package. Run it (F5). Still having trouble?
If so, let's update the controller method with a new line like this:
[HttpGet]
public IQueryable Todos() {
var items = _contextProvider.Context.Todos.ToList(); // test the query
return _contextProvider.Context.Todos;
}
Put a breakpoint on the var items ... line and re-run with the debugger (F5). Step into that line. Did it throw (not good but interesting)? If not, how many items did you get? Zero? You should have 6.
If you can't get past this point, I don't think this is a Breeze problem. Breeze hasn't done anything yet. I'd be looking for something unexpected in your environment.
Let us know how it stands when you get to this point; if still stuck we'll be ready for next steps.
The sample from NuGet is set up to drop and re-create the database every time you run the code. Do you happen to have the database open in a SQL Management Studio? I ran into this as well.
Take a look at the BreezeSampleDatabaseInitializer class. Check out the comment that talks about preserving the changes between server sessions. If you change the class to implement the DropCreateDatabaseIfModelChanges interface it will only try to drop the database when you change the model.

Code First and Model First in the same project?

I have two databases that I am accessing. The first is against a contact database which I connected to using EF Model First; creating the edmx. I have since begun to learn the virtue of CODE First when working with Entity Framework, so I decided I would, in the same project, write the Product database using Code First techniques, allowing the database to be generated from the code I am writing.
Everything compiles fine. The problem occurs when I hit my harness and it attempts to create the Product database and retreive a list of values from one of the tables...
I get the folowing error "Could not find the conceptual model type for 'Core.Data.Account'", when I attempt to enumerate the ProductLines property (Line3 below).
1. using (var ctx = new ProductDb())
2. {
3. var lines = ctx.ProductLines.ToList();
4. this.litOne.Text = lines.Count.ToString();
5. }
After some research it appears that this message may be occuring because of multiple entities with the same name (regardless of namespace), however there is nothing in the ProductDb context with the name "Account".
There is a class in the OTHER context created by the Model First approach named "Account". But how/why would that make a difference? They each point to different databases i.e. different connection strings. Why would the ProductDb be attempting to create a table called Account, when it should be completely unaware of it's exstence?
thoughts?
Thank you as always!,
- G
I bumped into the same problem, but the other way around: first a DbContext + generated database and then generated an edmx off the database (just for a little presentation). It appeared to be a restriction in EF: EF currently has a restriction that POCO classes can't be loaded from an assembly that contains classes with the EF attributes.
The only thing you can do for now is keep the contexts in separate assemblies.

EF Code first database/table initialization - WHEN does it happen?

My application is using EF code-first design and all generally works very well.
Via a private configuration file, I can specify how I would like EF to handle changes to the db schema, and so create/recreate the relevant tables as desired - the options are "never" "create", "always", "onSchemaChanged" and (for the future) "onSchemaModified".
This works well - but I am getting lost in a couple of places .....
During development, I would like to use the hook as described in
"Database in use error with Entity Framework 4 Code First" - but this seems to execute on EVERY run of my program"
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context); // Maybe this does nothing if not needed
context.Database.SqlCommand("ALTER DATABASE Tocrates SET MULTI_USER")
}
So .. to real my question: Is there an override that I can use to detect whether EF will ACTUALLY be trying to modify the database, so I can set this SINGLE_USER stuff when needed? And if so, can I detect the reason EF it is doing so (see my list of options above) so I can log the reason for change?...
All help and suggestions are very much appreciated.
Unless you have set the database intializer to null initializers run always once (per application lifetime) when you are using a context for the first time. What then actually happens depends on the initializer (your inner _intializer):
For DropCreateDatabaseAlways and CreateDatabaseIfNotExists it's clear by their name what they do.
For DropCreateDatabaseIfModelChanges there is only the question if the model changed or not. EF detects this by comparing a model hash with a hash stored in the database. You can check this yourself by calling...
bool compatible = context.Database.CompatibleWithModel(true);
...within your custom InitializeDatabase and then decide based on the result if you want to send your SqlCommands or not. (Don't call this with a self-created context because it will cause the database to be intialized first before the model compatibilty is checked.) The parameter bool throwIfNoMetadata (which is true in my example) causes EF to throw an exception if the model hash in the database does not exist. Otherwise the method will return true in that case.
For a custom inner initializer: Whatever your code will do.

Entity Framework 4 and DB2: database generation error

We are using Entity Framework 4 RC on Visual Studio 2010 with DB2 version 9.7.3.4. I also have the VS Add-ins and can see the DB2 database in Server Explorer. I have created a very simple VS console project and it works fine against SQL Server, so I know it is valid. I have references to "IBM.Data.DB2.9.7.3" and "IBM.Data.DB2.Entity" in my project.
In app.config my connnection string is:
<add name="ProductContext"
providerName="IBM.Data.DB2"
connectionString="Database=DB2TEST;User ID=XXXX;PWD=XXXX;Server=XXXX;Persist Security Info=True;"/>
The first statement in my code is a database initializer:
DbDatabase.SetInitializer<ProductContext>(new DropCreateDatabaseIfModelChanges<ProductContext>());
During run-time when I reach a line that causes a change to the data context I get the error:
Model compatibility cannot be checked
because the database does not contain
model metadata.
Since I requested that the database be dropped, this does not seem to be a logical error. Does anyone know what the cause could be?
I would try to inherit from CreateDatabaseIfNotExists first, which will add the EdmMetadata table to the schema. I believe the error is that EF is saying that it cannot find that table.
So
DbDatabase.SetInitializer<ProductContext>(new CreateDatabaseIfNotExists<ProductContext>());
Run it once, then change to DropCreateDatabaseIfModelChanges once the EdmMetadata table exists.
Try removing the IncludeMetadataConvention like this:modelBuilder.Conventions.Remove<System.Data.Entity.Infrastructure.IncludeMetadataConvention>();
To avoid the "dbo" issue, just map all your entities using either DataAnnotation attributes or Fluent mapping:
[Table("Product", SchemaName = "MySchema")]
public class Category { //DataAnnotoaion approach
modelBuilder.Entity<Category>().ToTable("Categories", "MySchema"); //Fluent approach

Resources