I've created an ASP.NET core 5 Solution and it consists of different projects. The Startup class and DataContext class are not in the same project so when I'm going to add a new migration on the Data project where DataContext is located I get the following error.
Unable to create an object of type 'DataContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
It is the structure of the Solution:
I managed to solve the problem by adding the Startup project's name while adding a new migration, but this way seems annoying to add the project's name every time creating a new migration.
dotnet ef migrations add initialcreation -s ..\API\API.csproj
No database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.
I also add a new constructor with no parameter in the DataContext class and the result was the following error:
No database provider has been configured for this DbContext. A
provider can be configured by overriding the 'DbContext.OnConfiguring'
method or by using 'AddDbContext' on the application service provider.
If 'AddDbContext' is used, then also ensure that your DbContext type
accepts a DbContextOptions object in its constructor and
passes it to the base constructor for DbContext.
Finally, I added the OnConfiguring function on DataContext and now it is like this:
public class DataContext : DbContext
{
public DataContext() {}
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
this.ChangeTracker.LazyLoadingEnabled = false;
}
public DbSet<AppUser> Users { get; set; }
public DbSet<UserPhoto> Photos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlite("name=DefaultConnection");
}
}
}
And again I got a new error while creating a new migration:
A named connection string was used, but the name 'DefaultConnection'
was not found in the application's configuration. Note that named
connection strings are only supported when using 'IConfiguration' and
a service provider, such as in a typical ASP.NET Core application. See
https://go.microsoft.com/fwlink/?linkid=850912 for more information.
UPDATE:
Here is appsettings.json file:
"ConnectionStrings": {
"DefaultConnection": "Data Source=database1.db"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
I am trying to create a Microservices architecture. I have a stateless service combined with Entity Framework deployed on the Azure Service Cluster Fabric.
However my problem is when i have a Initializer with DropCreateDatabaseAlways the database is removed but not recreated.
I have the following Initializer:
class CompanyInitializer : DropCreateDatabaseAlways<CompanyContext>
{
protected override void Seed(CompanyContext context)
{
var companies = new List<Company>
{
new Company { Name = "AAA", City = "Eindhoven", Streetname="Street 12" },
new Company { Name = "BBB", City = "Rotterdam", Streetname = "Street 12" },
new Company { Name = "CCC", City = "Eindhoven", Streetname = "Street 12" }
};
companies.ForEach(s => context.Companies.Add(s));
context.SaveChanges();
base.Seed(context);
}
}
With the following context:
public class CompanyContext : DbContext
{
public CompanyContext(string connectionString) : base(connectionString)
{
this.Database.Connection.ConnectionString = connectionString;
Database.SetInitializer<CompanyContext>(new CompanyInitializer());
}
public DbSet<Company> Companies { get; set; }
}
And i am connecting these through the constructor of the stateless service:
public StatelessServiceCompany(StatelessServiceContext context)
: base(context)
{
_databaseConnectionstring = WebConfigurationManager.AppSettings["Entity.Framework.ConnectionString"];
_context = new CompanyContext(_databaseConnectionstring);
new CompanyInitializer().InitializeDatabase(_context);
}
And the connectionstring is as followed:
Data Source=*****.*****.****.***;Initial Catalog=******;Integrated Security=False;User ID=********;Password=********;Connect Timeout=30;Encrypt=True;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
The problem is that the database is dropped but never recreated. I believe there are rights missing to create a database through code on the Azure platform.
Secondly Service cluster fabric is not letting me enable migrations for the project. When enabling migrations via the Package manager console i get the following error:
"System.BadImageFormatException: Could not load file or assembly
'StatelessServiceCompany' or one of its dependencies. An attempt was
made to load a program with an incorrect format."
How can i solve this. I don't want to make a replicate of Entity Framework via Ado.net.
Edit
I solved my problem by deleting the Initializer and enabling migrations. The solution for enabling migration was in the Platform Target under Properties > Build. Switching the platform target between x64 and x86 seems to do the trick. The seed function in the configuration file is also a kind of initializer.
You questions consists of two issues:
Database initialisation and
Schema migrations
of which I will only address the first one as that is your primary concern.
These two issues might be connected as well as might not.
The initializer DropCreateDatabaseAlways, unsuprisingly, drops the database when you run the application but it does not recreate a new one immediately. Instead, it waits for the first context usage in particular application domain and only then recreates it.
https://msdn.microsoft.com/en-us/library/gg679506(v=vs.113).aspx
I have created a simple project using ASP.Net MVC template in Visual Studion 2013 Express for Web. It does not use any authentication. Then I installed EntityFramework (v6.0.1), EntityFramework.SqlServerCompact packages.
My DbContext class is very simple:
public class EditTestContext : DbContext
{
public EditTestContext() : base("EditTestContext")
{
}
public EditTestContext(string connectionString) : base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(
new DropCreateDatabaseIfModelChanges<EditTestContext>());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new EditTestConfig());
}
}
The actual context object is created in the Unit of Work class:
public class EditTestUoW:IEditTestUoW,IDisposable
{
private DbContext dbContext;
public EditTestUoW()
{
CreateDbContext();
}
private void CreateDbContext()
{
dbContext = new EditTestContext();//NEW DBCONTEXT OBJECT IS CREATED
dbContext.Configuration.LazyLoadingEnabled = false;
dbContext.Configuration.ProxyCreationEnabled = false;
dbContext.Configuration.ValidateOnSaveEnabled = false;
}
public IRepository<EditTestModel> EditTestRepo
{
get
{
return new EFRepository<EditTestModel>(dbContext);
}
}
}
The connection string being used is:
<add name="EditTestContext" connectionString="Data Source=
|DataDirectory|EditTestDb.sdf;Max Database Size=256;
Max Buffer Size=1024;File Mode=Shared Read;
Persist Security Info=False;" providerName="System.Data.SqlServerCe.4.0" />
Now when I try to access any thing using this Context like:
var rep=UoW.EditTestRepo;
var list=rep.GetAll().ToList();
I am getting following exception on rep.GetAll() function:
System.InvalidOperationException: Sequence contains no matching element
On digging deeper, IQueryable from Repository class (DbSet<EditTest>) is throwing following exception:
The context cannot be used while the model is being created. This exception may
be thrown if the context is used inside the OnModelCreating method or if the same
context instance is accessed by multiple threads concurrently. Note that instance
members of DbContext and related classes are not guaranteed to be thread safe.
I thought it might have been caused by ninject, but it is still there even after I removed it.
What I am doing wrong here or something (some assembly reference etc.) is missing?
Well after some other search on the issue, I got this MSDN forum link. As was suggested by Rowan, I tried to manually initialize the context using following statement in my EFRepository class:
dbContext.Database.Initialize(false);
The application failed way before it was hitting the GetAll() method. But this exposed the stack trace which gave me some direction:
[InvalidOperationException: Sequence contains no matching element]
System.Linq.Enumerable.Single(IEnumerable`1 source, Func`2 predicate) +2614017
System.Data.Entity.Utilities.DbProviderManifestExtensions.GetStoreTypeFromName
(DbProviderManifest providerManifest, String name) +146
.....Other Lines.....
System.Data.Entity.Internal.InternalContext.Initialize() +31
System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType
(Type entityType) +38
System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +138
System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +38
System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable
.get_Provider() +99
System.Linq.Queryable.Any(IQueryable`1 source) +50
Then searching for DbProviderManifestExtensions.GetStoreTypeFromName revealed that this is the line where EF was trying to get column type. I had specified UNIQUEIDENTIFIER for my Id column:
Property(x=> x.Id).HasColumnType("UNIQUEIDENTIFIER")
Once I commented this, all was well.
Though there is a request on Codeplex to provide the proper error message in case the column type is not valid for database provider.
Can SimpleMembership be used with EF model-first? When I try it, I get "Unable to find the requested .NET Framework Data Provider" when I call WebSecurity.InitializeDatabaseConnection.
To put it another way: I can't get the call to WebSecurity.InitializeDatabaseConnection to work when the connection string employs the System.Data.EntityClient provider (as it does when using the model-first paradigm).
To repro the issue, create an MVC 4 app, and replace the code-first UserProfile entity class (which you get for free with the MVC 4 template) with a model-first User class that you have created in the Entity Designer:
Create an MVC 4 app in VS 2012 and add a new, blank Entity Data
Model.
Add a new Entity named User to the model, with fields for Id,
UserName, and FullName. So, at this point, the User data entity is
mapped to a Users table and is accessed via a funky connection
string that employs the System.Data.EntityClient provider.
Verify that the EF can access the User entity. One easy way to do
that is to scaffold out a Users controller based on the User table
and its associated DbContext.
Edit the AccountModels.cs file to remove the UserProfile class and
its associated UsersContext class. Replace the references to the
(now missing) UserProfile and UsersContext classes with references
to your new User class and its associated DbContext class.
Move the call to InitializeDatabaseConnection from the
InitializeSimpleMembershipAttribute filter class to the
Application_Start method in Global.asax.cs. While you're at it,
modify the arguments to use your new User entity's connection
string, table name, and UserId column name.
Delete the (no longer used) InitializeSimpleMembershipAttribute
class and the references to it.
When you run the repro, it will get an Exception at the call to InitializeDatabaseConnection.
Bob
SimpleMembership can work with model first. Here is the solution.
1.InitializeSimpleMembershipAttribute.cs from MVC 4 Internet Application templete should look like this
namespace WebAndAPILayer.Filters
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
try
{
WebSecurity.InitializeDatabaseConnection("ConnStringForWebSecurity", "UserProfile", "Id", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("Something is wrong", ex);
}
}
}
}
}
2.Delete CodeFirst Classes from AcountModel.cs
3.Fix AccountCotroler.cs to work with your Model-first DbContext (ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl) method)
4.Define your "ConnStringForWebSecurity" connection string which is not same as that funky conn string for model-first db access, notice that we use provider System.Data.SqlClient not System.Data.EntityClient
<connectionStrings>
<add name="ModelFirstEntityFramework" connectionString="metadata=res://*/Context.csdl|res://*/Context.ssdl|res://*/Context.msl;provider=System.Data.SqlClient;provider
connection string="data source=.\SQLEXPRESS;Initial
Catalog=aspnet-MVC4;Integrated
Security=SSPI;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="ConnStringForWebSecurity" connectionString="data source=.\SQLEXPRESS;Initial Catalog=aspnet-MVC4;Integrated
Security=SSPI" providerName="System.Data.SqlClient" />
</connectionStrings>
That's a bug in MVC 4. There's a workaround in this blog post.
As an action filter, InitializeSimpleMembershipAttribute hooks into OnActionExecuting to perform the lazy initialization work, but this can be too late in the life cycle. The Authorize attribute will need the providers to be ready earlier if it needs to perform role based access checks (during OnAuthorization). In other words, if the first request to a site hits a controller action like the following:
[Authorize(Roles="Sales")]
.. then you’ll have an exception as the filter checks the user’s role but the providers aren’t initialized.
My recommendation is to remove ISMA from the project, and initialize WebSecurity during the application start event.
1 - You need to enable migrations, prefereably with EntityFramework 5
2 - Move your
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
to your Seed method in your YourMvcApp/Migrations/Configuration.cs class
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName", autoCreateTables: true);
if (!Roles.RoleExists("Administrator"))
Roles.CreateRole("Administrator");
if (!WebSecurity.UserExists("lelong37"))
WebSecurity.CreateUserAndAccount(
"lelong37",
"password",
new {Mobile = "+19725000000", IsSmsVerified = false});
if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
}
Now EF5 will be in charge of creating your UserProfile table, after doing so you will call the WebSecurity.InitializeDatabaseConnection to only register SimpleMembershipProvider with the already created UserProfile table (In your case, you can replace the "UserProfile" parameter value with your custom table name), also tellling SimpleMembershipProvider which column is the UserId and UserName. I am also showing an example of how you can add Users, Roles and associating the two in your Seed method with custom UserProfile properties/fields e.g. a user's Mobile (number).
3 - Now when you run update-database from Package Manager Console, EF5 will provision your table with all your custom properties
For additional references please refer to this article with sourcecode:
http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/
this problem caused by WebSecurity.InitializeDatabaseConnection can't use connection string with System.Data.EntityClient provider name.
providing dual connection string isn't sound good, so you can generate the connection string for EF model first in the constructor in the partial class.
the code is look like bellow
public partial class MyDataContext
{
private static string GenerateConnectionString(string connectionString)
{
var cs = System.Configuration.ConfigurationManager
.ConnectionStrings[connectionString];
SqlConnectionStringBuilder sb =
new SqlConnectionStringBuilder(cs.ConnectionString);
EntityConnectionStringBuilder builder =
new EntityConnectionStringBuilder();
builder.Provider = cs.ProviderName;
builder.ProviderConnectionString = sb.ConnectionString;
builder.Metadata = "res://*/MyDataContext.csdl|" +
"res://*/MyDataContext.ssdl|res://*/MyDataContext.msl";
return builder.ToString();
}
public MyDataContext(string connectionName) :
base(GenerateConnectionString(connectionName)) { }
}
with this trick you can use single connection string on your web config, but one problem you can't use default constructor on your datacontext, instead you should seed connection string name everywhere when you instantiate the datacontext. but it is not a big problem when you use dependency injection pattern.
I´m not able to work with EF and WebMatrix webSecurity class so to avoid this problem and go ahead:
Change my Ef model first to code first.
Change the connection string to use providerName="System.Data.SqlClient"(removing all the metadata information) or use the EF connection
In my case the model, data and web are different proyects so for me is not an issue to remove this information from the web.config on the web.project.
Nowadays websecuroty.initializedatabase dosen't run with EF connection string.
I wish this helps
I have seen various implementations for Entity Framework using unit of work and repository patterns. ideally I want to use interfaces for unit of work, database context, repository (for both generic and specific repositories) and instantiate them in the BootStrapper code on application startup. Is this actually possible?
samples checked:
http://microsoftnlayerapp.codeplex.com (doesn't have any separate unit of work class, the database context itself implements IUnitOfwork)
http://efmvc.codeplex.com (uses a database factory to instantiate database context without utilising DI and database context does not implement interface)
http://code.msdn.microsoft.com/ASPNET-MVC-Application-b01a9fe8 (instantiates database context and the repositories inside unit of work without any DI)
some implementations don't use any interface for database context and some instantiate database context and the repositories inside the UnitOfWork class and pass concrete context class in the constructor and some pass the interface for unit of work in the constructor for repository and it is totally confusing. Is there one best practice approach that allows DI and TDD when using Entity Framework 4.1? Is there a sample that demonstrates this?
I have next so far:
Declaration:
namespace Contracts // Contracts.dll
{
public interface IUserRepository : IUserRepository
{
}
}
Implementation:
namespace Data // Data.dll
{
class UserRepository : Contracts.IUserRepository
{
}
}
IoC utility:
namespace Core // Core.dll
{
public static class IoC
{
private static IUnityContainer _container = LoadContainer();
private static IUnityContainer LoadContainer()
{
var unitySection = (Microsoft.Practices.Unity.Configuration.UnityConfigurationSection)ConfigurationManager.OpenMappedExeConfiguration(
new ExeConfigurationFileMap { ExeConfigFilename = System.Web.HttpContext.Current.Server.MapPath(UserSettings.UnityContainerPath) },
ConfigurationUserLevel.None).GetSection("unity");
var container = new UnityContainer();
unitySection.Configure(container);
return container;
}
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
}
}
Unity.config:
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<containers>
<container>
<types>
<type type="Contracts.IUserRepository, Contracts" mapTo="Data.UserRepository, Data">
<lifetime type="singleton" />
</type>
</types>
</container>
</containers>
</unity>
</configuration>