Posts Tagged Instance Methods
Entity Framework 4 and SQLCE 4 CTPs Odds and Ends
There are already plenty of good walk through for using Code First with EF 4 CTP so this a mop of of some odds and ends I found useful. I’l update this post as further releases are made / I stumble across discover new features.
Adding the NuPack package
EF4 (currently at CTP2) is available as a NuPack package, soon to be NuGet. EFCTP4 can be added as a package by itself or the SQLCE.EntityFramework package can be added to a project and this will include EF4CTP as a dependency. This is my preferred root as I find it easier to develop with SQLCE then swap databases after most of the initial development is complete.
Presuming the solution has a separate project for a data layer, then that is the project the NuPack should be added to. The system.data element should then be copied from the web.config of the data layer (where the Nupack added it) to the web.config of the web front end.
Viewing the SQLCE 4 Database
The SQLCE tooling for VS 2010 and SSMS is yet to be released. WebMatrix alows some examination of SQL CE 4 database files, alternatively basic info can be viewed in VS2010 using SQL Server Compact Toolbox which is a VS addin that can be downloaded from the extension gallery.
Reseeding the database for each run
When developing it is useful to have the database in a known condition each time it is run. When the SQLCE Entity Framework package installed it added a AppStart_SQLCEEntityFramework class. We can use the start method of this class to set an initializer for the database:
Database.SetInitializer(new RavenInitializer());
We can then specify an initializer to recreate the database every time the app is started and prepopulate it:
public class RavenInitializer : AlwaysRecreateDatabase<RavenContext> {
#region Instance Methods
protected override void Seed(RavenContext context) {
var tenants = new List<Tenant>
{
new Tenant
{
Id = 1,
Name = "Tenant 1",
PaidupUntil = DateTime.Now.AddMonths(1),
SubscriptionLevel = 1
},
new Tenant
{
Id = 2,
Name = "Tenant 2",
PaidupUntil = DateTime.Now.AddMonths(-1),
SubscriptionLevel = 2
}
};
tenants.ForEach(t => context.Tenants.Add(t));
}
#endregion
}
Conventions
Primary Key
If a class has a field called either Id or <class name>Id then that field will be used as a primary key.
Named Connection String
If a connection string exists in Web.Config with the same name as the context, EF4 will use it in preference to the standard db factory (see below for an example).
Coming Soon (as of CTP2)
The following are features that are not in CTP2 but are documented in various blogs.
Type Discovery
Currently, if EntityA has a property of type EntityB, EntityB will not persist to the database unless it has a DbSet exposed by the context or is registered as a complex type with the ModelBuilder. In a future release EntityB will be persisted automatically.
Bug Fix for ‘The database File already Exists’
There is currently an issue with EF4 CTP2, it attempts to recreate your SQLCE database every run resulting in an exception being thrown. The 2 workarounds for this are either to revert to CTP1 or specify a connection string in the web.config and remove the DataDirectory macro.
<connectionStrings>
<add name="RavenContext"
connectionString="Data Source=Raven.sdf"
providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>
Not ideal but hopefully this will be fixed for the next release and we can go back to “Data Source=|DataDirectory|Raven.sdf”
DI with Ninject for an MVC project
This seems to be a somewhat moving target with ASP.Net MVC moving up the versions as well as Ninject. This particular target will be ASP.Net MVC 2.0 and Ninject 2.0.
First set up the references:
- Download Ninject.Web.Mvc (If not using git, there is a download source link on the page).
- Open the mvc2/Ninject.Web.Mvc.sln and compile with release settings.
- Copy the files Ninject.dll and Ninject.Web.Mvc.dll from the mvc2/build/debug/release folder to the lib folder of your MVC project.
- Add references to these two files to your MVC project.
The DI Container (called a Kernel with Ninject) needs initializing on app startup which, with MVC, is in the Global.asax. Add the following using statements to the Global.asax:
using Ninject; using Ninject.Modules; using Ninject.Web.Mvc;
Change the MvcApplication so it inherits from NinjectHttpApplication:
public class MvcApplication : NinjectHttpApplication {
Let Visual Studio implement the CreateKernel method.
override the OnApplicationStarted method copying in the lines from the Application_Start method:
protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RouteRegistrar.RegisterRoutes(RouteTable.Routes);
}
Then delete the Application_Start method.
Ninject stores the rules it uses to return class instances in Modules which are derived from NinjectModule. Add the following class to the MVC project:
using Ninject.Modules;
namespace MvcApp.Web {
public class WebModule : NinjectModule {
#region Instance Methods
public override void Load() {
}
#endregion
}
}
The Load method is where we specify how each request for a concrete class is fulfilled.
Lastly, modify the CreateKernel method so that the module is passed into the Kernel’s ctor:
protected override IKernel CreateKernel() {
var modules = new INinjectModule[]
{
new WebModule()
};
var kernel = new StandardKernel(modules);
return kernel;
}