EF Core empty migration issue - entity-framework-migrations

I am using .Net Core 2.1 and EF Core 2.1. I successfully created 2 tables with EF Code First Migrations and dotnet CLI also seeded data into it. However when I try to add a new model Feature, and run the migration, the file generated has empty Up() and Down() methods and there is no entry in the EF_MigrationsHistory table of Database and the modelSnapshot.cs file also doesn't contain any references to the Feature model. I cross checked the ApplicationDbContext to see if I accidentally missed the declaration of the model in the class but I hadn't. I am not sure of the issue. Can anyone help me out with this? Posting the codes from my project:
Feature.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ProjectName.Models
{
public class Feature
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
}
}
ApplicationDbContext.cs
using Microsoft.EntityFrameworkCore;
using ProjectName.Models;
namespace ProjectName.Persitance{
public class ApplicationDbContext: DbContext{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> context)
: base(context){ }
public DbSet<Make> Makes { get; set; }
public DbSet<Feature> Features { get; set; }
}
}
20180906063933_AddFeature.cs(Migration File):
using Microsoft.EntityFrameworkCore.Migrations;
namespace ProjectName.Migrations
{
public partial class AddFeature : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
ApplicationDbContextModelSnapshot.cs:
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Application.Persitance;
namespace Application.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Application.Models.Make", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255);
b.HasKey("Id");
b.ToTable("Makes");
});
modelBuilder.Entity("Application.Models.Model", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("MakeId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255);
b.HasKey("Id");
b.HasIndex("MakeId");
b.ToTable("Models");
});
modelBuilder.Entity("Application.Models.Model", b =>
{
b.HasOne("Application.Models.Make", "Make")
.WithMany("Models")
.HasForeignKey("MakeId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}
__EFMigrationsHistory DB Image:

Usually this happens when you include context.Database.EnsureCreated(); in your seed data file. This method doesn't allow to create a migrations table and cannot be used with migrations. You need to remove migrations with Remove-Migration command or delete the Migration folder and the database in your server and create new migration. Check Microsoft docs for better understanding.

I was having a similar issue. The Up method was empty despite cleaning the migrations folder and running dotnet ef migrations add Initial multiple times.
The solution in my case was to change the DbSet properties and add virtual to each of them.
Instead of
public DbSet<Make> Makes { get; set; }
try
public virtual DbSet<Make> Makes { get; set; }

Related

Setting up for selective auditing in same DbContext

I just stumbled onto Audit.Net and I'm hooked. I went through the Audit.Net Entity Framework (6) documentation and am a bit lost in the output part.
My solution is a bit many-layers design:
Mvc 5 website
Wcf Client
Using WcfClientProxyGenerator
Wcf Service
Separate IService Contracts Library
All interfaces expose BDOs
Business Logic
Seperate BDO Library
Data Access
Reference EF6
Reference Audit.Net
DTOs
Entity Framwework Library
Has EDMX only
Reference Audit.Net
Reference: My EDMX is named Focus
Usage
I manage to modify the FocusModel.Context.tt from:
partial class <#=code.Escape(container)#> : DbContext
To:
partial class <#=code.Escape(container)#> : Audit.EntityFramework.AuditDbContext
Configuration
I found the default setting for Mode, IncludeEntityObjects, & AuditEventType were to my liking. the attribute for Include/Ignore entities/properties were straightforward as well.
Output
This is where I'm confused. I need to audit to the same database preferably to Audit tables for selected entities. Every entity in my database has composite PKs. How do I set the output mode in this scenario? Also, in my solution setup, the starting point for all projects that are behind the WCF Service is the WCF service itself. Does this mean that the point to Fluent-API-configure Audit.Net is here?
Have you seen the main Audit.NET documentation, specifically the output data providers?
I need to audit to the same database preferably to Audit tables for selected entities. Every entity in my database has composite PKs.
So you can use the EF data provider. It works with any kind of primary key.
How do I set the output mode in this scenario?
I'm not sure what do you mean by output mode, but I'm guessing you ask about OptIn/OptOut to ignore your audit entities to be audited. If that's the case you have multiple options, like using AuditIgnore attribute on your audit POCO classes, or via the fluent-api OptIn()/OptOut() methods. See example below.
The starting point for all projects that are behind the WCF Service is the WCF service itself. Does this mean that the point to Fluent-API-configure Audit.Net is here?
You can configure the Audit.NET library in any place, but you must do it before any audit event creation, so it is recommended to be on your startup code, as soon as your app or service starts.
Sample code
The following is a minimal example showing how you can configure the Audit.NET and Audit.EntityFramework libraries.
Suppose you have the following schema:
public class Student
{
public int PK_1 { get; set; }
public string PK_2 { get; set; }
public string Name { get; set; }
}
public class Student_Audit
{
public int PK_1 { get; set; }
public string PK_2 { get; set; }
public string Name { get; set; }
public DateTime AuditDate { get; set; }
public string AuditAction { get; set; }
}
public class SchoolContext : AuditDbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder) //<--Tip: its not DbModelBuilder, its Microsoft.EntityFrameworkCore.ModelBuilder
{
modelBuilder.Entity<Student>().HasKey(c => new { c.PK_1, c.PK_2 });
modelBuilder.Entity<Student_Audit>().HasKey(c => new { c.PK_1, c.PK_2, c.AuditDate });
}
public DbSet<Student> Students { get; set; }
public DbSet<Student_Audit> Students_Audit { get; set; }
}
You can configure the library on your startup code as follows:
// Setup audit to use the EF data provider
Audit.Core.Configuration.Setup()
.UseEntityFramework(_ => _
.AuditTypeExplicitMapper(m => m
// Map Student to Student_Audit
.Map<Student, Student_Audit>((ev, ent, studentAudit) =>
{
//add the action name and the date to the audit entity
studentAudit.AuditAction = ent.Action;
studentAudit.AuditDate = DateTime.UtcNow;
})));
// Configure the EF audit behavior
Audit.EntityFramework.Configuration.Setup()
.ForContext<SchoolContext>(_ => _.IncludeEntityObjects())
.UseOptOut()
.Ignore<Student_Audit>(); // Do not audit the audit tables
And a test case:
using (var db = new SchoolContext())
{
db.Database.EnsureCreated();
var st = new Student() { PK_1 = 1, PK_2 = "one", Name = "John" };
db.Students.Add(st);
db.SaveChanges();
}
Will generate the following:

How to filter breeze.webapi returned entities from the server

I have a standard breeze web-server which exposes the Project
[HttpGet]
public IQueryable<Project> Projects()
{
return _db.Context.Projects;
}
How can i prevent a Project with NoLongerExist=true from begin included in queries returned to the JavaScript client from here affecting the functionality of the breezejs client?.. um i would also like to hide this property also, people wont like to see that their projects are not actually deleted!
you can try this on your breeze controller...
public IQueryable<Project> Projects()
{
return _db.Context.Projects.Where(o => o.NoLongerExist == true);
}
prevent json serialization of the NoLongerExist property using data annotations on your model by doing this, i'm assuming you are using EF6 with JSON.NET on your backend...
[Table("Project")]
public partial class Project
{
public Project()
{
}
public int id { get; set; }
[JsonIgnore]
public bool NoLongerExist { get; set; }
}

EF Core + MVC 6 + .NET Core RC2 - EF not returning results

Entity Framework Core is not returning any results. I've been searching near and far. I find some tutorials saying one thing and others saying another. Here is what I have so far:
Buyer.cs
[Table("DealerCustomer", Schema = "dbo")]
public class Buyer
{
[Key]
public int DealerCustomerKey { get; set; }
public int DealerId { get; set; }
}
BuyerContext.cs
public class BuyerContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("db connection string here");
}
public DbSet<Buyer> Buyers { get; set; }
}
Startup.cs > ConfigureServices function
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddDbContext<BuyerContext>(options =>
options.UseSqlServer("db connection string here");
services.AddMvc();
}
Now I am trying to load the Buyers data from my BuyerController.cs:
[Route("api/[controller]")]
public class BuyersController : Controller
{
private BuyerContext _context;
public BuyersController(BuyerContext context)
{
_context = context;
}
[HttpGet]
public IEnumerable<Buyer> Get()
{
System.Diagnostics.Debug.WriteLine("getting buyers");
System.Diagnostics.Debug.WriteLine(_context.Buyers);
return _context.Buyers;
}
}
This is all returning empty brackets when I load the page, instead of a list of Buyers. However there are over 1000 rows in that table (dbo.DealerCustomer). I know I have two places adding the db connection string but tutorials kept show both ways of doing it and when I only did it in startup.cs I was getting errors about the _context. I can make everything look pretty later, right now I just want a good connection so I have a starting place to work from.
I found there was a timeout because one of the decimal fields was returning null.
EF Core Timing out on null response

Code First migrations with multiple DbContexts fail when setting default schema

I have two projects each with their own DbContext class that write to the same SQL Server 2012 database.
The DbContext classes are of the form:
public class BlogDbContext : DbContext
{
public BlogDbContext()
: base("CodeFirstTestConnString")
{
}
public BlogDbContext(string connectionString)
: base(connectionString)
{
}
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.HasDefaultSchema("blogtest");
}
}
Using Code First Migrations I can create my tables in the (existing) database by executing the following in each project:
Enable-Migrations
Add-Migration Initial
Update-Database
This works fine, however if I add in the line commented out above to set the default schema (both projects use the same schema), Update-Database fails in the second project with the error "There is already an object named '__MigrationHistory' in the database.".
By running "Update-Database -Verbose" I can see that with the default schema changed, "CREATE TABLE [blogtest].[__MigrationHistory]" is executed for the second project; if I don't change the default schema it only tries to create this table the first time.
Is this a bug in Entity Framework, or am I missing something?
Turns out that this is reported in Codeplex as a bug in EF6.
https://entityframework.codeplex.com/workitem/1685
The workaround shown there is to use a custom HistoryContext to set the default schema:
internal sealed class Configuration : DbMigrationsConfiguration<ConsoleApplication11.MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetHistoryContextFactory("System.Data.SqlClient", (c, s) => new MyHistoryContext(c, s));
}
}
internal class MyHistoryContext : HistoryContext
{
public MyHistoryContext(DbConnection existingConnection, string defaultSchema) : base(existingConnection, defaultSchema)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema("foo");
}
}

MVC update model with Code-Migrations

I am making my project in MVC4, where i am using my Code first approach. i need to update my model
i have a following property which needs to be update , how can i achieve this
public class ContactForm
{
public char Phone { get; set; }
}
public class ConContext : DbContext
{
public DbSet<ContactForm> ContactForms { get; set; }
}
}
i want to update Phone propery to
public char Phone { get; set; }
thnx in advance, i have installed migrations to my projet already
My configuration.cs
namespace MyCRM.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<MyCRM.Models.ConContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MyCRM.Models.ConContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
}
The normal flow with EF code-first is too first update the model (a C# file) :
public class ContactForm
{
public string Phone { get; set; } //previously, this was let's say of type int
}
Then, you build your project and after that in the Package Manager Console, you have to call Add-Migration with some label (in order to rollback changes later if needed) :
Add-Migration Phone
This will add to your solution a file named like this 201409xxxxxxxx_Phone under the directory Migrations.
Then you have to put the changes to your database which can be done with the command (always in the console) :
Update-Database
Then, you should be done : the property Phone is of type string everywhere.

Resources