Been playing around with the Code First feature of Entity Framework 4.1 using an ASP.NET MVC 3 project.
However the database (SQL Server 2008 R2) does not automatically create the table mapping on application startup. Any ideas on how to make it do so?
The project has only one POCO:
namespace RIS.Models
{
public class Person
{
[Key]
public virtual string NRIC { get; protected set; }
public virtual string FirstName { get; protected set; }
public virtual string MiddleName { get; protected set; }
public virtual string LastName { get; protected set; }
}
}
It also has the following database context class:
namespace RIS.Models
{
public class RIS_DB : DbContext
{
public DbSet<Person> People { get; set; }
}
}
I've added a SQL connection string to the global web.config file as follows:
<add name="RIS_DB" connectionString="Data Source=URAHARA-PC;Initial Catalog=RIS_DB;
Integrated Security=SSPI;Pooling=False" providerName="System.Data.SqlClient"/>
There is also an explicit instruction to create the database if it does not exist in the Global.asax.cs file:
protected void Application_Start()
{
Database.SetInitializer(new CreateDatabaseIfNotExists<RIS_DB>());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Asked around on the MSDN forums instead, and got a satisfactory answer:
Entity Framework will not create a database until first access. The current code block in Application_Start() only specifies the strategy to use when creating the database during first access.
To trigger creation of the database on startup, an instance of the database context must be created, and context.Database.Initialize(true) must be invoked.
I have the same issue and found a elegant solution: call the SetInitializer in the constructor of your DbContext:
public class MyDbContext : DbContext
{
protected MyDbContext : this("MyConnection")
{
Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>());
}
}
My app setting:
<connectionStrings>
<add
name="MyConnection"
connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\MyDB.mdf;Initial Catalog=MyDB;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
I know this was already answered by mazatsushi in the rightest way.
But just to clarify it to begginers:
Based in mazatsushi's answer what you have to do is to write:
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SorteoContext>());
using (var context = new SorteoContext())
{
context.Database.Initialize(force: true);
}
inside Application_Start() function in Global.asax.cs
and Boom! works!
Related
I am trying the new functionality with EF Core 2.2. It is based on the following article. "Announcing Entity Framework Core 2.2"
https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-entity-framework-core-2-2/
I installed the following Nuget package.
I added the following to my model.
using NetTopologySuite.Geometries;
//New as of EF.Core 2.2
//[Required]
//[NotMapped]
public Point Location { get; set; }
During my application startup I get the following error in my Database Context on the following line:
Database.EnsureCreated();
System.InvalidOperationException
HResult=0x80131509
Message=The property 'Point.Boundary' is of an interface type ('IGeometry'). If it is a navigation property manually configure the relationship for this property by casting it to a mapped entity type, otherwise ignore the property using the NotMappedAttribute or 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
Source=Microsoft.EntityFrameworkCore
You need to call UseNetTopologySuite(). Example here:
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString = configuration.GetConnectionString("DefaultConnection");
optionsBuilder.UseSqlServer(connectionString, opts => opts.UseNetTopologySuite());
}
public DbSet<Test> Tests { get; set; }
}
public class Test
{
public int Id { get; set; }
public Point Location { get; set; }
}
I ran into this problem because I had a
if (!optionsBuilder.IsConfigured) around everything in my OnConfiguring. I had to remove this in order to get add-migrations to work.
As Kyle pointed out you need to call UseNetTopologySuite(), but I would call it during ConfigureServices like this:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddEntityFrameworkNpgsql()
.AddDbContext<MyDBContext>(opt =>
opt.UseNpgsql(Configuration.GetConnectionString("MyDBConnection"),
o=>o.UseNetTopologySuite()))
.BuildServiceProvider();
...
}
...
}
I'm using the SimpleMembership.MVC3 package with my MVC3 application and I want to be able to access users from the table through Entity Framework
In examples for doing this with MVC4, you can simply create a POCO to mirror the User table that's been generated, add your DbSet in your DbContext implementation and then query the DbSet like you normally would, ie: context.Users.
This collection is always returning 0 items for me even though there are rows in the table. What am I doing wrong? Here's what I got so far:
[Table("User")]
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
In my service:
model.Accounts = context.Users.ToList();
Thanks!
You do not create your a POCO that mirrors the User table in order to access it directly from EF. There is already a POCO created by the Internet template when you created the project, which you can customize as described here. This same article also shows how you can access the user information by accessing EF directly. You do not create your own context, there is one already in place that you use. Here is a code snippet from that article.
var context = new UsersContext();
var username = User.Identity.Name;
var user = context.UserProfiles.SingleOrDefault(u => u.UserName == username);
var email = user.Email;
The article also has links to download the source code that demonstrates the details on how to do this.
I circumvented the membership classes entirely and implemented a pure EF membership system. I leveraged the System.Web.Helpers Crypto helpers to handle password hashing and just create the AuthCookie when needed.
I'm creating a new MVC 3 pilot application using Mvc3 and the MvcScaffolding NuGet, everything runs smoothly until i want to use the database i already have. The application keeps creating a database with the format:
projectname.Models.projectnameContext
I'm stuck in here, my connectionStrings is:
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
<add name="EnginesTrackingEntities" connectionString="metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=WARCHLAPPY\SQLEXPRESS;initial catalog=[EnginesTracking];integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
In which specifies that my database is EnginesTracking.
Update
I'm following the database first approach from this example.
I have everything working perfectly but when the application starts, it creates a new table instead of using the one i specified.
The only one difference is that there is no databaseEntities in my project, instead there is projectContext for which i cannot do the number 8 step
Update2
I'm kinda given up on this, going to follow codeFirst approach as this is taking to much time for only being a pilot.
This is the Model1.context.cs:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ErrorReportingSystem.Models{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class EnginesTrackingEntities : DbContext
{
public EnginesTrackingEntities()
: base("name=EnginesTrackingEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Engine_Part> Engine_Part { get; set; }
public DbSet<Engines> Engines { get; set; }
public DbSet<Error> Error { get; set; }
public DbSet<Has_error> Has_error { get; set; }
public DbSet<Locations> Locations { get; set; }
public DbSet<Operators> Operators { get; set; }
public DbSet<sysdiagrams> sysdiagrams { get; set; }
}
}
I finally found the problem. I found a similar issue here which finished pointing me in the right direction.
I had to add:
public ErrorReportingSystemContext() : base("name=EnginesTrackingEntities") { }
To the ErrorReportingSystemContext.cs file under /Models folder.
Done!
Seems like you are using Code First Entity Framework. The post will probably get the best exposure in that forum. EnginesTrackingEntities is an EF connect string.
One of the big problems in dealing with code-first is the db drop and re-create with every change to your POCO's.
I strongly prefer database first approach because it is not as hard to deploy (not hard at all) and where you are pointing is clear. The advantage of code first is being able to elegantly style and decorate your POCO's.
I'm not exactly answering your question due to lack of info, but helping direct you. With a little more info on your deployment and Entities, I may be able to help more.
I'm a newbie using Ninject and I can't figure out how to inject into my generic http handler. I have a MVC3 project and I'm injecting my services into controllers with no problem at all.
This is what I got in my Ninject App_start class for registering services:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<NLSubscriber.Core.Service.Repository.INLUserRepository>().To<NLSubscriber.Core.Service.Repository.EFDAL.EFNLUserRepository>().InRequestScope();
kernel.Bind<Neticon.Mvc.Helpers.IConfigHelper>().To<Neticon.Mvc.Helpers.AzureEnabledConfigHelper>().InSingletonScope();
kernel.Bind<Neticon.Security.Service.IAuthenticationService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateAuthenticationService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IMembershipService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateMembershipService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IRoleManagerService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateRoleManagerService()).InRequestScope();
When I try to get some service from my generic handler by using property injection (with [inject] attribute) I always get null. This is how my handler looks like:
public class SubscriberHandler : IHttpHandler
{
[Inject]
public INLUserRepository userRep { get; set;}
public void ProcessRequest(HttpContext context)
{
var users = userRep.GetUsers(); //userRep is always null here
}
public bool IsReusable
{
get
{
return false;
}
}
}
I have also tried doing it like this:
readonly INLUserRepository userRep;
public SubscriberHandler()
{
using (IKernel kernel = new StandardKernel(new App_Start.NJRepositoryModule()))
{
userRep = kernel.Get<INLUserRepository>();
}
}
but I'm getting an exception: "Error loading Ninject component ICache. No such component has been registered in the kernel's component container.
Suggestions:
1) If you have created a custom subclass for KernelBase, ensure that you have properly
implemented the AddComponents() method.
2) Ensure that you have not removed the component from the container via a call to RemoveAll().
3) Ensure you have not accidentally created more than one kernel."
That's suggesting me that I'm not supposed to instantiate more than one kernel in my application, right?
What am I doing wrong?
Thanks
You could use the dependency resolver:
public class SubscriberHandler : IHttpHandler
{
public INLUserRepository userRep { get; private set; }
public SubscriberHandler()
{
userRep = DependencyResolver.Current.GetService<INLUserRepository>();
}
public void ProcessRequest(HttpContext context)
{
var users = userRep.GetUsers(); //userRep is always null here
}
public bool IsReusable
{
get
{
return false;
}
}
}
I am expecting to get negative feedback from this answer because the service locator pattern is considered by many as an anti-pattern.
But I am not sure whether NInject allows you to use constructor injection for HTTP handlers because they are instantiated by the ASP.NET runtime.
The composition root for IHttpHandlers is the IHttpHandlerFactory. You can create a custom IHttpHandlerFactory that uses Ninject to create an instance of your IHttpHandler. That way you can use constructor injection.
I see you have a "RegisterServices" method in your snippet which suggests you're already using Ninject.Web.Common. What you might not know about NinjectWebCommon.cs is it uses a Bootstrapper class which contains a singleton instance of the Ninject kernel.
As Remo mentioned above, IHttpHandlerFactory is the composition root for IHttpHandler instances and as such you will need to create an implementation of this interface and add the necessary configuration elements to your web.config.
MyHandlerFactory.cs:
public class MyHandlerFactory : IHttpHandlerFactory
{
public bool IsReusable => false;
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
// the bootstrapper class uses the singleton pattern to share the Ninject Kernel across your web app's ApplicationDomain
var kernel = new Bootstrapper().Kernel;
// assuming you have only one IHttpHandler binding in your NinjectWebCommon.cs
return kernel.Get<IHttpHandler>();
}
public void ReleaseHandler(IHttpHandler handler)
{
// nothing to release
}
}
Now, add the necessary config elements for your new handler factory...
Web.config:
<system.web>
<httpHandlers>
<add verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="MyHandlerFactory" verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" preCondition="integratedMode" />
</handlers>
</system.webServer>
Finally, add a binding for your IHttpHandler implementation...
NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<NLSubscriber.Core.Service.Repository.INLUserRepository>().To<NLSubscriber.Core.Service.Repository.EFDAL.EFNLUserRepository>().InRequestScope();
kernel.Bind<Neticon.Mvc.Helpers.IConfigHelper>().To<Neticon.Mvc.Helpers.AzureEnabledConfigHelper>().InSingletonScope();
kernel.Bind<Neticon.Security.Service.IAuthenticationService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateAuthenticationService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IMembershipService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateMembershipService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IRoleManagerService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateRoleManagerService()).InRequestScope();
// the binding for your handler factory
Bind<IHttpHandler>().To<SubscriberHandler>();
}
I have ASP.NET MVC3 project where I want to use custom membership provider. Also I want to use Unity for resolving my dependency injection.
this is code from Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container.RegisterType<IAuthentification, Authentification>();
container.RegisterType<IRepository, Repository>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
this is code from my membership provider:
public class CustomMembershipProvider : MembershipProvider
{
[Dependency]
private IProveaRepository Repository { get; set; }
public override bool ValidateUser(string username, string password)
{
.....
}
Problem is when I put breakpoint to ValidateUser method I see that Repository property not initialized. But this construction:
[Dependency]
private IProveaRepository Repository { get; set; }
for example, works fine in controllers.
Does anybody know why it is so and what to do?
I had the same problem over the last couple of days. I ended up with the following solution (type and field names changed to match yours).
public class CustomMembershipProvider : MembershipProvider
{
private IProveaRepository repository;
public CustomMembershipProvider()
: this (DependencyResolver.Current.GetService<IProveaRepository>())
{ }
public CustomMembershipProvider(IProveaRepository repository)
{
this.repository= repository;
}
public override bool ValidateUser(string username, string password)
{
...
}
}
So even though Unity is not in control of the building of the CustomMembershipProvider, the parameterless constructor gets Unity involed (via the MVC3 DependencyResolver) to supply the correct repository instance.
If you're unit testing the CustomMembershipProvider then you can just build an instance with Unity directly, which will use the second constructor and avoid the call to DependencyResolver.
Unity cannot inject IProveaRepository instance into you custom membership provider because :
You did not configured it to do so
CustomMembershipProvider is not resolved by unity so it has no control on injecting into it the dependencies
If you're using your membership priovider class in your code you could do the following :
Try to wrapp your customMembershipProvider in an abstraction for example IMembershipProvider that has only signature for methods that you use. The result is like that :
public class CustomMembershipProvider : MembershipProvider, IMembershipProvider
Then you could register it in unity :
container.RegisterType<IMembershipProvider, CustomMembershipProvider>(new InjectionProperty(new ResolvedParameter<IProveaRepository>()));
Then the constraint is to pass the dependency in your controller like that :
public class HomeController : Controller
{
private IMembershipProvider _membershipprovider;
public HomeController(IMembershipProvider membershipProvider)
{
_membershipProvider = membershipProvider
}
// some actions
}
But it would be event better to not user the property injection but the constructor injection like that :
public class CustomMembershipProvider : MembershipProvider
{
private IProveaRepository Repository { get; set; }
public CustomMembershipProvider(IProveaRepository proveaRepository)
{
Repository = proveaRepository
}
public override bool ValidateUser(string username, string password)
{
.....
}
It's the way I understand it and would do it. But maybe there is a better approach or I'm ignoring some of Unity API that would help to achieve it easier.
Anyway I hope it helps.
While as others said Unity cannot inject dependencies in providers because they're not known
to the container and, even if could be a registration of a provider, you haven't a "factory point" where building the provider through the container, there's a solution which doesn't violate good design principles. (This because, even if most people ignore this, using a ServiceFactory is too close to an antipattern...)
But, a good solution could be the association of using the [Dependency] attribute in conjunction with the Unity BuildUp method.
So taking your example, to get what you're trying to do, leave all the things as they are, and put in the provider constructor the BuildUp call
public class CustomMembershipProvider : MembershipProvider
{
[Dependency]
private IProveaRepository Repository { get; set; }
public CustomMembershipProvider()
{
//contextual obtained container reference
unityContainer.BuildUp(this);
.....
}
public override bool ValidateUser(string username, string password)
{
.....
}
I hope it helps.