Fail in calling Enable-Migrations for a generic DbContext class - ef-code-first

Let's assume that I have this Entity Framework (v6.0) DbContext-based class, sitting in the "Food.Common" assembly:
public class FoodContext<T> : DbContext where T : Food<T>
{
public FoodContext() : base("MyConnectionString")
{
}
public DbSet<T> FoodElements { get; set; }
}
The above Food generic class is also sitting in the "Food.Common" assembly, and it is defined as:
public class Food<T> where T : Food<T>
{
// some code here...
public virtual T Copy()
{
// object copy goes here...
}
}
Also, I have this class which inherits from Food<T> and sits on the "Food.Extras" assembly:
public class HealthyFood : Food<HealthyFood>
{
// some code here...
public override HealthyFood Copy()
{
var baseCopy = base.Copy();
// extending the baseCopy with more data...
}
}
Now, I can easily instantiate and use the FoodContext<T> context like this:
using (var context = new FoodContext<HealthyFood>())
{
// some CRUD for "healthy food" goes here...
}
and the appropriate table is automatically created by EF in the database.
The problem is: when trying to call the "Enable-Migrations" command after updating the HealthyFood class (the model), I get notified by the Package Manager Console that "No context type was found in the assembly Food.Common".
My suspicion is that since the "Food.Common" does not contain a concrete (non generic) DbContext-based class, the "Enable-Migrations" thinks there's no context type inside this assembly at all.
So, how can I tell the Enable-Migrations that I want to update a concrete DbContext class (such as the FoodContext<HealthyFood>)?
Already tried Enable-Migrations -ContextTypeName Food.Common.FoodContext<HealthyFood> with no luck...

Related

Prism XF: issue with creating 'child' view-models

I can see in the source code of Prism this
Container.RegisterType<INavigationService, UnityPageNavigationService>(_navigationServiceName);
Why is it using a specific name? Why not have this:
Container.RegisterType<INavigationService, UnityPageNavigationService>();
I am asking because I'm having a hard time with child view-models:
class ItemViewModel : BindableBase
{
public ItemViewModel(INavigationService navigationService)
{
}
}
and I'm creating items on a page:
class MainPageViewModel : BindableBase
{
public IEnumerable<ItemViewModel> Items { get; private set; }
public MainPageViewModel(Funct<ItemViewModel> itemFactory)
{
}
public void OnNavigatedTo(NavigationParameters parameters) {
Items = ... // Create items, where each item is created using itemFactory
}
}
But the DI fails, it throws exception because it cannot create ItemViewModel:
Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the
dependency failed, type = "MyApp.ViewModels.ItemViewModel", name =
"(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, Prism.Navigation.INavigationService, is an interface and cannot be
constructed.
Are you missing a type mapping?
In Xamarin Forms navigation is based on the page being Navigated from. As such the Prism Forms PageNavigationService must be aware of the page which is associated with that particular instance of the service. In order to facilitate this, we register the service with a "secret" key, and then resolve the service and pass it in using the named instance "navigationService" for the ViewModel to consume.
You should not be using the NavigationService outside of the context of a ViewModel unless of course you are performing an absolute navigation (resetting Application.MainPage).
Note that each DI Container handles this a little differently, and each one uses a slight variation of the registration key, all of which is easy enough to look up with Prism being Open Source.

StructureMap 4 with named instances not working as expected

Here is a simplified version of a couple of classes in my solution and the interfaces they implement. They both share one interface and also implement a dedicated interface.
public interface ISharedContract
{
void ImplementSharedContract();
}
public interface IConcreteOne
{
void ImplementConcreteOne();
}
public interface IConcreteTwo
{
void ImplementConcreteTwo();
}
public class ConcreteOne : BaseConcrete, IConcreteOne, ISharedContract
{
public void ImplementSharedContract()
{
this.ImplementConcreteOne();
}
public void ImplementConcreteOne()
{
}
}
public class ConcreteTwo : BaseConcrete, IConcreteTwo, ISharedContract
{
public void ImplementSharedContract()
{
this.ImplementConcreteTwo();
}
public void ImplementConcreteTwo()
{
}
}
My StructureMap registry registers these dependencies as follows:
public class MyRegistry : Registry
{
public MyRegistry()
{
this.For<ISharedContract>().Use<ConcreteOne>().Named("cOne");
this.For<ISharedContract>().Use<ConcreteTwo>().Named("cTwo");
this.For<IConcreteOne>().Use<ConcreteOne>();
this.For<IConcreteTwo>().Use<ConcreteTwo>();
}
}
Finally I have a class which injects these dependencies in the constructor as follows:
public MyDependent(ISomethingElse somethingElse, ISharedContract cOne, ISharedContract cTwo)
{
this.collection = new List<ISharedContract>()
{
cOne,
cTwo
};
}
At runtime I observe that cOne and cTwo are both injected instances of ConcreteTwo. If I swap the order of the two named registrations in the StructureMap registry then cOne and cTwo are both instances of ConcreteOne.
This isn't the first time I've used named instances but I've not observed this before. Is there something I'm missing? I've checked and double-checked that the values passed to the Named method correspond with the parameter names in the constructor.
Update
Here is the updated registry entry which is needed to make my example case work. Thanks to #jeremy-d-miller for the info I needed:
this.For<IMyDependent>().Use<MyDependent>()
.Ctor<ISharedContract>("cOne").Is<ConcreteOne>()
.Ctor<ISharedContract>("cTwo").Is<ConcreteTwo>();
StructureMap doesn't have any magic functionality here that is matching your constructor parameter names to the named instance of that type. You would have to explicitly map the inline dependencies in this case: http://structuremap.github.io/registration/inline-dependencies/
In this code:
this.For<ISharedContract>().Use<ConcreteOne>().Named("cOne");
this.For<ISharedContract>().Use<ConcreteTwo>().Named("cTwo");
You're setting the default ISharedContext to ConcreteOne, then immediately overriding that to ConcreteTwo. Last one wins in this case. When you're building your MyDependent class, StructureMap is just using auto-wiring to push in the default instance of ISharedContext.

DropCreateDataBaseAlways is not working when working with multiple db schemas with Entity Framework 6 Code First

After watching the "Enhancements to Code First Migrations: Using HasDefaultSchema and ContextKey for Multiple Model Support" section of Julie Lerman's PluralSite video, "Entity Framework 6: Ninija Edition-What's New in EF 6" (https://app.pluralsight.com/library/courses/entity-framework-6-ninja-edition-whats-new/table-of-contents), it seems there is a way to run multiple schemas under a single database in Entity Framwork 6 using Code First Migrations...
However, based on the video you still need to these package manager commands for each project that houses a separate context:
1. enable-migrations
2. add-migration [MIGRATION NAME]
3. update-database
This is fine and good if you actually care about maintaining migrations going forward, which is not a concern of mine.
What I'd like to do is have each of my Context's initializers set to DropCreateDatabaseAlways, and when I start up my client app (in this case, an MVC site), code first will create the database for the first context used, create the tables in with the correct schema for that context, and then create the tables for the rest of the contexts with the correct schema.
I don't mind if the whole database is dropped and recreated every time I hit F5.
What is happening now is the last context that is accessed in the client app is the only context tables that are created in the database... any contexts being accessed before the last get their tables blown away.
I am currently using two contexts, a Billing context and a Shipping context.
Here is my code:
My client app is an MVC website, and its HomeController's Index method looks like this:
public ActionResult Index()
{
List<Shipping.Customer>
List<Billing.Customer> billingCustomers;
using (var shippingContext = new Shipping.ShippingContext())
{
shippingCustomers = shippingContext.Customers.ToList();
}
using (var billingContext = new Billing.BillingContext())
{
billingCustomers = billingContext.Customers.ToList();
}
}
Here is my DbMigrationsConfigurationClass and ShippingContext class for the Shipping Context:
internal sealed class Configuration : DbMigrationsConfiguration<ShippingContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(ShippingContext context)
{
}
}
public class ShippingContext : DbContext
{
public ShippingContext() : base("MultipleModelDb")
{
}
static ShippingContext()
{
Database.SetInitializer(new ShippingContextInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Shipping");
base.OnModelCreating(modelBuilder);
}
public DbSet<Customer> Customers { get; set; }
class ShippingContextInitializer : DropCreateDatabaseAlways<ShippingContext>
{
}
}
Likewise, here is the DbMigrationConfiguration class for the Billing Context and the BillingContext class:
internal sealed class Configuration : DbMigrationsConfiguration<BillingContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(BillingContext context)
{
}
}
public class BillingContext : DbContext
{
public BillingContext() : base("MultipleModelDb")
{
}
static BillingContext()
{
Database.SetInitializer(new BillingContextInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Billing");
base.OnModelCreating(modelBuilder);
}
public DbSet<Customer> Customers { get; set; }
class BillingContextInitializer : DropCreateDatabaseAlways<BillingContext>
{
}
}
based on the order that the contexts are being called in the controller's action method, whichever context is accessed last is the only context that is created... the other context is wiped out.
I feel like what I'm trying to do is very simple, yet code first migrations, as well as trying to "shoehorn" Entity Framework to represent multiple contexts as separate schemas in the same physical database seems a bit "hacky"...
I'm not that versed with migrations to begin with, so what I'm trying to do might not make any sense at all.
Any feedback would be helpful.
Thanks,
Mike

Instantiate DbContext-derived class with Mehdime.Entity AmbientDbContextLocator

can anyone tell me what I am doing wrong?
I am wanting to use Mehdime.Entity from https://www.nuget.org/packages/Mehdime.Entity in order to manage my DBContext-derived classes in a Console Application. I am also using NInject.
The connection strings for my DBContext-derived classes are partially generated from standard app.config ConnectionStrings and also by an AppDomain value that (in my Console App case) comes in via a command line argument.
My DBContext-derived classes have their connection strings prepared using a program-implemented class which takes into account of the command line argument as follows:
public class TaskManagementDbContext : DbContext
{
public TaskManagementDbContext(IConnectionStringResolver csr) :
base(csr.GetConnectionString("Default"))
{
}
}
(IConnectionStringResolver basically implements GetConnectionString() which returns the connection string by using given named standard app.config ConnectionString and the command line argument.
This is fine when I use NInject to instantiate the DbContext directly but when trying to use with Mehdime.Entity, it is AmbientDbContextLocator that is doing the instantiation and it throws a MissingMethodException because it requires my DBContext-derived class to have a parameterless constructor:
public class TaskRepository : ITaskRepository
{
private readonly IAmbientDbContextLocator _ambientDbContextLocator;
private TaskManagementDbContext DbContext
{
get
{
// MissingMethodException thrown "No parameterless constructor defined for this object"
var dbContext = _ambientDbContextLocator.Get<TaskManagementDbContext>();
...
}
}
How should I provide a connection string to my DBContext-derived classes at run-time in this situation? I suspect I am going about this the wrong way. Thanks.
OK. I've worked out the solution and I'm putting it here for anyone else with this issue:
Create your own implementation of IDbContextFactory (see below). I put this in the same class library as my Data Access Layer (i.e. my DbContexts). You will see in my example how I "look for" a specific constructor prototype (in my case, 1 parameter of type IDbContextFactory - your's will no doubt be different). If found, get the actual parameters and invoke a new instance of your DBContext-derived class. If not found, you can throw an exception or in my case, try to call the default constructor (if exists).
Code:
using System;
using System.Data.Entity;
using Mehdime.Entity;
using Ninject;
using TaskProcessor.Common;
namespace TaskProcessor.Data.Connection
{
public class DbContextWithCSRFactory : IDbContextFactory
{
public TDbContext CreateDbContext<TDbContext>() where TDbContext : DbContext
{
// Try to locate a constuctor with a single IConnectionStringResolver parameter...
var ci = typeof(TDbContext).GetConstructor(new[] { typeof(IConnectionStringResolver) });
if(ci != null)
{
// Call it with the actual parameter
var param1 = GlobalKernel.Instance.Get<IConnectionStringResolver>();
return (TDbContext)ci.Invoke(new object[] { param1 });
}
// Call parameterless constuctor instead (this is the default of what DbContextScope does)
return (TDbContext)Activator.CreateInstance<TDbContext>();
}
}
}
Create a binding in NInject so that your IDbContextFactory implementation is called:
Code:
private void AddBindings(IKernel kernel)
{ ...
kernel.Bind<IDbContextFactory>().To<Data.Connection.DbContextWithCSRFactory>().InSingletonScope();
}
Everything now falls into place.

How to inject different instance(s) for different context in ASP.NET MVC using StructureMap?

We are using classes inheriting from Registry to configure our StructureMap container in our ASP.NET MVC 4 application startup.
Some excerpt from one of the registry-classes:
For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeImplementation>();
We would like use different instances of our interfaces depending on the context. (For example switching from database "online" mode to "maintenance" mode where everything is saved on filesystem; therefore using other interfaces (i.e. repositories) all over the place in our application)
For example by default it should use SomeImplementation but when passing some kind of querystring in the url (to name a simple "context" scenario) it should use SomeOtherImplementation.
How can this be achieved for multiple interfaces/types?
Should we use named instances for this? Like:
For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeOtherImplementation>().Named("other");
I read about StructureMap Profiles but i'm not sure if this is the right way to go.
Should we use profiles for this? Like i.e.:
Profile("other", profileExpression =>
{
For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeOtherImplementation>();
});
How can we switch different configurations on the fly?
ObjectFactory.Container.SetDefaultsToProfile("other");
This way? (At what stage in mvc "life-cycle" this can happen at the earliest?)
Can this be a temporary switch for just the current request or current users session?
Thanks in advance!
From my experience, runtime configuration like this is best achieved using an abstract factory that is responsible for creating your dependency during runtime.
This dependency can then be registered with StructureMap like so:
Your registry:
public class StorageRegistry : Registry
{
public StorageRegistry()
{
...
this.For<IDataStoreInstance>().Use(ctx => ctx.GetInstance<DataStoreAbstractFactory>().ConfigureStorage());
...
}
}
Now your DataStoreAbstractFactory is responsible for creating and configure the necessary storage instance based on your configuration. As DataStoreAbstractFactory is now registered with StructureMap you're able to inject the necessary dependencies into it for determining which storage method to use.
Implementation example:
public class DataStoreAbstractFactory
{
public DataStoreAbstractFactory()
{
// Dependencies to figure out data storage method can be injected here.
}
public IDataStoreInstance ConfigureStorage()
{
// This method can be used to return type of storage based on your configuration (ie: online or maintenance)
}
}
public interface IDataStoreInstance
{
void Save();
}
public class DatabaseStorage : IDataStoreInstance
{
public void Save()
{
// Implementation details of persisting data in a database
}
}
public class FileStorage : IDataStoreInstance
{
public void Save()
{
// Implementation details of persisting data in a file system
}
}
Usage:
Your controller/services or whatever are now completely unaware of what storage method they're using when accessing and persisting data.
public class UpdateController : Controller
{
public IDataStoreInstance StorageInstance { get; set; }
public UpdateController(IDataStoreInstance storageInstance)
{
StorageInstance = storageInstance;
}
[HttpPost]
public ActionResult Index()
{
...
this.StorageInstance.Save();
...
}
...
}

Resources