In the application I'm building the very first thing the client does is request the breeze metadata. If the database does not exist and entity framework needs to create the database it will not seed using the initializer configured with Database.SetInitializer.
If something else triggers EF to do a query against the dbcontext first then the database is seeded as expected.
I'm not sure if this is a bug or intended for some reason?
Thanks
I'm pretty sure the bug is on your end. I have no trouble retrieving metadata first at which point the database is created and seeded. Do it all the time.
You can see this for yourself in any of the Breeze Todo samples. Remember that your first Breeze client query always asks for metadata before processing your query so the first call to the server (in these samples) is always a request for metadata. These samples would not work if a request for metadata failed to generate the database.
The Todos sample initializes and seeds the database in a trivial way in the class ctor (the static ctor). Here's the entire TodosContext.cs
namespace Todo.Models {
using System.Data.Entity;
public class TodosContext : DbContext
{
// DEVELOPMENT ONLY: initialize the database
static TodosContext()
{
Database.SetInitializer(new TodoDatabaseInitializer());
}
public DbSet<TodoItem> Todos { get; set; }
}
}
To see it in action:
Show all files
Delete the *App_Data/todo.sdf* database
Set breakpoints on that constructor and on the methods of the Web API controller.
Run with debug (F5) ... you'll see the metadata endpoint hit first, then this static constructor.
Look at the *App_Data* folder in Windows Explorer and confirm that the database was created.
Continue ... you'll see the Todos query endpoint hit.
Continue ... the screen fills with seeded todos.
How are you doing it?
Related
I am using Entity Framework to create and seed my database using Code First and the MigrateDatabaseToLatestVersion initializer. The issue I am having is when I launch the ASP.NET MVC app without a database create EF will create the database but will not seed on the first run through. If I kill iisexpress and relaunch the app after creating the database my seeds go in fine. I would expect my seeds to be ran after the database gets created but I don't even hit a break point in my seeds method on the first run through. I hit break points on the second run through without problems but it is annoying to have to run the app twice after killing the DB just to get my seeds to work.
Below is my Configuration class:
public sealed class Configuration : DbMigrationsConfiguration<CompassDb>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(CompassDb context)
{
ModuleSeed.Seed(context);
PermissionGroupSeed.Seed(context);
var permissions = PermissionSeed.Seed(context);
var roles = RoleSeed.Seed(context, permissions);
UserSeed.Seed(context, roles, permissions);
OcmPluginSeed.Seed(context);
SCACSeed.Seed(context);
ModuleConfigurationSeed.Seed(context);
}
}
I am calling this in my Global.asax file.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<CompassDb, Configuration>());
using (var db = new CompassDb())
{
db.Database.Initialize(true);
}
I did have a query to get a version number from the db on page load to create the database but calling the initializer directly seems a little cleaner. I was having the issue before when I was making a DB call through EF as well. I moved away from the DB call because I am only using EF for the automatic DB creating and migration then I switch to Dapper for any database communication.
I found this post here where people were having the same issue as me but it doesn't seem like it was ever resolved.
UPDATE
I found out that the issue is related to my migration files. I updated the primary keys of all my models from int to long and had to delete my current migration files. After deleting the files everything started working as normal, the database would be created and seeded on the same request. I then created my initial schema migration and am back at the same issue where the database does not seed until the 2nd time launching the site. I am using ELMAH in the project and have to update the first migration file to execute the sql file that is included when installing ELMAH via nuget. This could be related to the issue and I will do more testing to see if this is the cause.
I think I had the same or similar problem. Try to make a manual initializer. It's clean, simple and short. See this example:
Public Class CustomDbInit
Implements IDatabaseInitializer(Of MyContext)
Public Sub InitializeDatabase(context As MyContext) Implements System.Data.Entity.IDatabaseInitializer(Of MyContext).InitializeDatabase
If Not context.Database.Exists Then
context.Database.CreateIfNotExists()
' Some other processes, such as WebMatrix initialization if you're using SimpleMembership like I do
End If
End Sub
End Class
Then on the Global.asax Application_Start method, initialize it like this:
Dim context As New MyContext()
If Not context.Database.Exists Then
Database.SetInitializer(New CustomDbInit())
context.Database.Initialize(False)
End If
I have a non-standard BreezeController query which returns a "fake" IQueryable as a resource to query from the client using the standard breeze EntityQuery js class. This fake query builds up a collection of Entity objects mapped by Entity Framework and therefore known by breeze in memory and returns these as an IQueryable.
I have isolated the problem to be something to do with writing a projection query that's selecting a property that is populated in memory on the server as a Child collection of other instances of the same Entity type.
This query was working as of breeze 1.4.2. After upgrading to 1.4.6 (and related libraries), this query now returns an error response to the client: "The query specified in the URI is not valid".
I have stepped through the server-side query method in the BreezeController and see that the in-memory list of objects are being constructed without an exception being thrown. Once control passes back to breeze and the rest of the response pipeline something is occurring that causes the error response back on the client.
In order to investigate the problem further I need to step through more of the response pipeline but not sure how best to achieve this.
I have tried switching on the Visual Studio option "Enable .NET framework source stepping", but this doesn't seem to be able to locate/download sufficient number of the debug symbols to step into the things like Breeze, JSON, Web API, OData, etc.
I've tried configuring Visual Studio to break as soon as a CLR exception is thrown. But no exception appears to be thrown on the server side.
I'm wondering if someone from Breeze can provide some advise? Maybe there are some additional code hooks in breeze I can write some of my own code to plug into simply so that I can set some breakpoints and further isolate the stage in the pipeline that is having issues.
Thanks
Christian
A: How to debug a breeze query on the server.
Until such times as breeze publishes the .pdb files for each of it's dll's you will need to download the source from Github, compile, and manually copy the pdb files into the breeze NuGet package(s):
Download breeze source code
Browse to https://github.com/IdeaBlade/Breeze
Download the version of the source code that matches the vs of breeze you need to debug (Tip: You will need to use the Branches button to select a specific tag)
Compile the breeze source code:
Open the VS solution file - Breeze.Build.sln
With Visual Studio open, change to Release build using the Configuration Manager dialog (this assumes you want to debug a set of release build dll's - the ones that Breeze.js publish in their NuGet)
Rebuild the solution - this will build an exact copy of the dll's within the breeze NuGet packages, along with their assoicated .pdb files
Copy the pdb files into the corresponding NuGet lib directory:
For example: \bin\Release\Breeze.ContextProvider.pdb -> packages\Breeze.Server.ContextProvider.n.n.n\lib
Copying the pdb files into the NuGet package was the only way I could get Visual Studio to recognise and load the pdb files when wanting to step through. I tried loading the symbols by right clicking on the call stack frame but VS complained when I pointed to the pdb file in the breeze source code bin directory.
Stepping through the breeze server side query
It looks the main body of interesting code that you want to debug is found in the BreezeQueryableAttribute and associated helper class QueryHelper. The easiest way I found to step into this code is to create a subclass of BreezeQueryableAttribute and within this subclass override the OnActionExecuted method. Decorate the IQueryable method
in the BreezeController with this new attribute.
With the new subclasses attribute in place, you can set a breakpoint on the OnActionExecuted in the subclass and step into the BreezeQueryableAttribute.OnActionExecuted from there.
For convenience here's the subclassed attribute I created:
using Breeze.WebApi2;
public class DebugBreezeQueryable : BreezeQueryableAttribute
{
public override void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
}
}
A: Why did the projection query over a "fake" IQueryable fail after upgrading?
It was as I suspected: the QueryableAttribute.ValidateQuery was complaining about trying to $select an EF/breeze unmapped property (in this case a property named Children). It's interesting that this worked fine in vs 1.4.2 of breeze.
The workaround I came up with was to instead create a DTO class that is not mapped to the database and populate instances of these DTO's in memory from the Entity objects loaded from the database; to return these DTO's as an IQueryable. The key I believe is that these DTO classes are not mapped in EF/breeze.
For completeness here's an extract of the interesting code involved in the failing query:
Client side query:
query = breeze.EntityQuery
.from("ScreenEntityUIs")
.where("id", "==", parseInt(id, 10))
.select("Id, EntityId, Children, AdditionalData, IsModal, IsList");
Server side query:
public IQueryable<EntityUI> ScreenEntityUIs()
{
var sql = BuildEntityUIsQuery();
var all = this.contextProvider.Context.Database.SqlQuery<EntityUI>(sql).ToList();
var results = new List<EntityUI>();
var roots = all.Where(p => p.ParentId == null);
foreach (var root in roots)
{
this.BuildChildrenList(root.Id, all, root);
results.Add(item);
}
return results.AsQueryable();
}
Entity class:
public class EntityUI : StateInfo
{
public EntityUI()
{
this.Children = new Collection<EntityUI>();
}
public int Id { get; set; }
public int? ParentId { get; set; }
[NotMapped]
public virtual ICollection<EntityUI> Children { get; set; }
/* snip */
}
Can you post the relevant server side endpoint code and the client side query that it is trying to execute.
Per your 2nd question, the Breeze source is available on GitHub and you can download and debug directly into the Breeze EF libraries by changing your refs to point directly to downloaded versions of the source.
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.
I am in search of an good approach to import data from ms access and bind it to any Model of an MVC pattern
Here is the approach which we are thinking to following
Approach 1 :
Open Ms Access file
Open database
Open all tables
Import data of all tables and bind them to an model
Close all tables
Close database
Close file
Approach 2 :
Connect Ms Access Database in Asp.Net MVC
Open the database
pass an query
fetch data and bind it to model
close database
Which approach is better and how I can Implement it?
UPDATE:
I have implemented Approach 2 and its works fine , does anyone know how to implement Approach 1
Both approaches will require you to connect to your database and map the contents into your model. I'm assuming Approach 1 is 'when the web app starts connect and copy all the database contents into memory and access if from there' and Approach 2 is 'when I need to display some data, connect the the database and copy the specific contents to my model'.
If this is the case, then Approach 2 is recommended (and you've stated you have done this so all is good).
Approach 1 may work ok-ish for smaller sized databases but:
You loose all the [acid][1]-y goodness that your database provides
Your stuck with global collection variables - not the most loved concept in web apps
You have an entire database unnecessarily in memory. Your slow point in web apps is usually the network, a few milliseconds to load data when needed is nothing compared with the time it takes for your html to reach the browser
If you were to try approach one (not recommended, do not do, a kitten is harmed each time this code is run) , then the easiest way would be to have something like this in your global.asax.cs file:
public class MvcApplication : System.Web.HttpApplication {
public static List<MyTable1> globalTable1;
public static List<MyTable2> globalTable2;
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var DatabaseMagic = new DatabaseAccessClass("a:\path\to\database.mdb");
globalTable1 = DatabaseMagic.getDataForTableOne(); //However you do your loading and mapping
globalTable2 = DatabaseMagic.getDataForTableTwo(); //ditto
}
Then in your controllers:
public ActionResult Index()
{
return View(MvcApplication.globalTable1);
}
And your view:
#model List<MvcApplication1.MvcApplication.MyTable1>
#{
ViewBag.Title = "Index";
}
<h2>Blah</h2>
<ul>
#foreach (var i in Model) {
<li>#i.idField - #i.contentField </li>
}
</ul>
(Did I mention don't do this?)
Use Entity Framework.Create ViewModel to map.
What you should do is build your model according to your table. So the model class should have properties which correspond to your table fields. Then when you require the Model you would query againist the DB and populate the model's properties accordingly.
I did not understood Approach 1.
Is it a requirement to use Access? I have seen there are lot of problems with file based database (such as Access) so better import all the data to SQL Server or some other database from Access and then use option 2.
As your database already created you can use Entity Framework database first approach to bind it.
You need to add using System.Data.OleDb; in Header file
And add these Provider=Microsoft.ACE.OLEDB.12.0;DataSource=|DataDirectory|\myAccessFile.mdb;
Persist Security Info=False; line in connection string use connection string fetch
update ms-access database using OleDbCommand , OleDbConnection
and ms-access query just like sql query
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)
{
}
}