I'm rewriting some code from EF5 into EF6. As part of the process I'm attempting to split my database context logic out into a class library. This worked before when part of the main project but now results in blank up/down methods when running add-migration.
public class SLDBContext : DbContext
{
public SLDBContext()
: base("name=SLApi")
{
System.Data.Entity.Database.SetInitializer(new CreateDatabaseIfNotExists<SLDBContext>());
}
public DbSet<Language> Languages { get; set; }
public DbSet<Template> Templates { get; set; }
public DbSet<TemplateFolder> TemplateFolders { get; set; }
public DbSet<Element> Elements { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
}
Running add-migration MagicWombat with my class library selected in the Package Manager Console gives me this:
public partial class MagicWombat : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
My seed methods are empty but I would expect it to create me some empty tables non-the-less. Obviously I'm missing something, but what?
If your DbContext is no longer inside your startup project you need to use the -StartUpProjectName switch, so that EF can look at the config file there for the connection string.
add-migration MagicWombat -StartUpProjectName YourProject
if you've selected your class library as default in PM console, otherwise:
add-migration MagicWombat -ProjectName YouClassLibrary -StartUpProjectName YourProject
Related
I have a Table "IncomingChecks" in my database. I've created it using EF Code first. Now, I've added a view to my database based on this table named "ViewIncomingChecks" using Sql Server Management Studio and I want to use its data in my app using Entity Framework.
I copied the model class and changed its name and added it to the context:
public class ViewIncomingCheck
{
[Key]
public int Id { get; set; }
//...
}
public class CheckDataContext : DbContext
{
public virtual DbSet<ViewIncomingCheck> ViewIncomingChecks { get; set; }
//...
}
now when I run the app, it throws an exception saying the DB Context has been changed and needs a migration. I even tried to add a migration (which seems to be the wrong option) and when I add the migration, it says that the object ViewIncomingChecks is already in the database.
How can I use this view in my code?
Edit
My current solution is to have another context just for the views. This way it doesn't conflict with the EF Migrations. Is this the best option or is there a better way to deal with it.
According to what I have done in my project:
First add public virtual DbSet<ViewIncomingCheck> ViewIncomingChecks
{ get; set; } to your DbConext
Now create a migration something called ViewDbSetAdded
Remove all the code from the both Up and Down method and it will look like as follows:
Migration Code:
public partial class ViewDbSetAdded : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Now run update-database command and it will run an empty migration.
I am using entity framework core in a normal .net project, version 4.7. I know I can do this. The problem is that I can't seem to map an entity to a table because the "ToTable" method doesn't exist. I can't edit the poco or entity classes because they are predefined and generated. So I can't use the attribute. I looked on the internet and everyone seems to use this method to map an entity to a table.
Here is my code:
public class FactsDbContext : DbContext
{
public DbSet<TblIncident> TblIncidents { get; set; }
public DbSet<TblAction> TblActions { get; set; }
public DbSet<TblAddressTypeAlias> TblAddressTypeAliases { get; set; }
public DbSet<TblCountry> TblCountries { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//these methods don't exist in my case
modelBuilder.Entity<TblIncident>(entity => entity.ToTable("Incident"));
modelBuilder.Entity<TblIncident>().ToTable("Incident");
}
}
I also tried to use IEntityTypeConfiguration with a EntityTypeBuilder but it still don't have access to the map to table method:
public class IncidentConfig : IEntityTypeConfiguration<TblIncident>
{
public void Configure(EntityTypeBuilder<TblIncident> builder)
{
builder.ToTable("Incident");
}
}
I looked into the Entity Framework Core repository on GitHub and searched for the method "Totable" inside the repository. It turns out it is defined as an extension method but it is in separate nuget package and library called Microsoft.EntityFrameworkCore.SqlServer
After I downloaded the package I got the Totable method that I need. Still it doesn't make sense to add that method in a separate package for sql server when you already have the "Table" attribute that you can add on entities directly in the entity framework core package.
You can use the below approach. You have to use Table data annotation.
DBContext:
public virtual DbSet<Article> Article { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Article>(b =>
{
b.Property(e => e.Property1).HasDefaultValue(true);
... //Other properties
}
Model class:
[Table("Article")]
public class Article
{
You can also use to ToTable in DBContext, but you have to make sure that you have included using Microsoft.EntityFrameworkCore;.
Line modelBuilder.Entity<TblIncident>().ToTable("Incident"); looks correct according to the documentation.
https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables#fluent-api
It's very old thread but I got the same issue and I solved it by placing base.OnModelCreating(builder) as a first line of OnModelCreating method.
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Rest of the code
}
I use entity framework 6.1.3 model first approach.
I needed to design a simple model as following.
Then i generated sql to create the database but i found that my entities sets were not defined in my DbContext. I tried to add them manually but Entity Framework keeps regenerating the following code.
It only generates the abstract entity which is exactly the opposite of what it is designed for.
public partial class UploadsDataModelContainer : DbContext
{
public UploadsDataModelContainer()
: base("name=UploadsDataModelContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<AzureBlobs> AzureBlobs { get; set; }
}
Is this a bug in EF code generator or am i missing a step in model creation ?
Thanks to RicardoPeres i added a class file with the following content and it resolved my problem by avoiding the automatic updates of the DbContext.cs file :
public partial class UploadsDataModelContainer : DbContext
{
public virtual DbSet<Chunk> CHunks { get; set; }
public virtual DbSet<Upload> Uploads { get; set; }
}
In my solution I have some database contract project that stores interfaces for contexts and some project for concrete Ef contexts, something like below:
public interface ISampleContext
{
IDbSet<User> Users { get; set; }
IDbSet<Session> Sessions{ get; set; }
}
public class SampleContext : DbContext, ISampleContext
{
IDbSet<User> Users { get; set; }
IDbSet<Session> Sessions { get; set; }
SampleContext() : base("name=EfDefaultConnectionString"){ ... }
SampleContext(string connectionString) : base(connectionString){ ... }
protected override void OnModelCreating(DbModelBuilder modelBuilder) { ... }
}
I run the command for migration (enable, add, update, etc.) by below pattern:
Add-Migration
-Name MigrationName
-ProjectName EfProjectName
-StartUpProjectName EfProjectName
-ConfigurationTypeName EfProjectName
-ConnectionStringName SomeConnectionStringName
But after running the commands, Ef migration fails. For solve problem, I should comment interface(s) and : base("name=EfDefaultConnectionString"). finally, after create migration uncomment code.
My question is why when provide connection string name, package manager console not call the SampleContext(string connectionString) constructor and I get below exception?
No connection string named 'EfDefaultConnectionString' could be found in the application config file.
And second question is can I control the flow of running commands in package manager console?
last question is not exactly related to this problem, but I need now Is there any way run migration commands when "EntityFramework.dll" and "EntityFramework.SqlServer.dll" "copy local" is false?
I made a new ASP.Net Web Application and enabled migrations on it. I ran add-migration initial and the initial migration does in fact have all the default tables for authentication (dbo.AspNetRoles, dbo.AspNetUserRoles, etc). However, when I create my own context and add an entity model to it, I can't get migrations to acknowledge that model. That is, when I run add-migration added-watchedgame-model I just get an "empty" migration file. So what am I doing wrong? Does my DbContext have to be referenced somehow? can Entity Framework only handle migrations for 1 dbcontext?
ReleaseDateMailerDBContext.cs:
using System.Data.Entity;
using WebApplication4.Models;
namespace WebApplication4.DataAccess
{
public class ReleaseDateMailerDBContext : DbContext
{
public ReleaseDateMailerDBContext() : base("DefaultConnection") { }
public DbSet<WatchedGameModel> WatchedGameModelSet { get; set; }
}
}
WatchedGameModel.cs:
using System.ComponentModel.DataAnnotations;
namespace WebApplication4.Models
{
public class WatchedGameModel
{
public int ID { get; set; }
[MaxLength(1024)]
public string URL { get; set; }
public string Email { get; set; }
public bool EmailSent { get; set; }
}
}
"empty" migration file:
namespace ReleaseDateMailer.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class addedwatchedgamemodel : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
"Batch Clean" may resolve your porblem.
It suggests that the EF tooling/assemblies are looking in a location other than the default build output location (typically /bin/Debug). The clean command also, incidentally, clears intermediary outputs.
To do a batch clean:
Select Build -> Batch Build
Click Select All
Click Clean
Close dialog, rebuild and re-attempt migration.
While running the add-migration command your package manager console should be pointed to the project having your DBContext class (WebApplication4.DataAccess).
If you have migration in a different project than your web application project (suppose WebApplication4.Web) then you should run the following command:
add-migration "MigrationName" -projectName:WebApplication.DataAccess -startupProjectName:WebApplication4.Web
Hope it helps!!
With the built-in asp.net mvc project, a DbContext class (ApplicationDbContext) is already
created!
When you enter enable-migrations, a migration configuration class is created based on the dbcontext class that it finds.
When you enter add-migration "migrationname", That dbcontext class is what is checked for differences.
So all one has to do is, rather than making one's own class that derives from DbContext, use that one.