Gray Wolf Corporation

Here are a few changes I came across migrating a medium sized app from 4.7.2 to Core 2.1.

There are some pretty significant differences, especially with model annotations. Fluent API handles most of the configuration now.

Global changes, such as a default string length, take a bit more effort to implement.

Indexes can no longer be created through data annotations and must be created through fluent api

EF6

  [Index("IX_ClientApplication", 1, IsUnique = true)]
  public int ClientUserId { get; set; }

  [Index("IX_ClientApplication", 2, IsUnique = true)]
  public int ClientApplicationId { get; set; }

EF7

modelBuilder.Entity<ClientUserClientApplication>()
  .HasIndex(x => new { x.ClientUserId, x.ClientApplicationId })
  .IsUnique();

HasRequired is now HasOne when setting table props through fluent api

EF7

 modelBuilder.Entity<ClientApplication>()
        .HasOne(c => c.Client)
        .WithMany(c => c.ClientApplications)
        .HasForeignKey(c => c.ClientId);

WillCascadeOnDelete(false) replaced with .OnDelete(DeleteBehavior.Restrict)

EF6

modelBuilder.Entity<ClientApplicationRoleClaim>()
  .HasRequired(x => x.ClientApplicationRole)
  .WithMany(x => x.ClientApplicationRoleClaims)
  .WillCascadeOnDelete(false);

EF7

modelBuilder.Entity<ClientApplicationRoleClaim>()
  .HasOne(x => x.ClientApplicationRole)
  .WithMany(x => x.ClientApplicationRoleClaims)
  .OnDelete(DeleteBehavior.Restrict);

HasOptional has no equivalent in EF7 - null foreign key will make the relationaship optional under the hood.

EF6

modelBuilder.Entity<Fund>()
  .HasOptional(c => c.Distributor)
  .WithMany()
  .WillCascadeOnDelete(false);

EF7

modelBuilder.Entity<Fund>()
  .HasOne(c => c.Distributor)
  .WithMany()
  .HasForeignKey(x => x.DistributorId)
  .OnDelete(DeleteBehavior.Restrict);

IDbSet is gone in EF7

SO article

Removing pluralization takes a bit more work

EF6

modelBuilder.Conventions
  .Remove<PluralizingTableNameConvention>();

EF7

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{                  
  modelBuilder.Entity(entityType.Name)
    .ToTable(entityType.Name.Replace("PAC.ETL.Model.",""));
}

So does setting default string length

EF6

modelBuilder.Properties<string>()
  .Configure(p => p.HasMaxLength(50));
  

EF7

foreach (var property in modelBuilder.Model.GetEntityTypes()
        .SelectMany(t => t.GetProperties())
        .Where(p => p.ClrType == typeof(string)))
    {
        if (property.GetMaxLength() == null)
            property.SetMaxLength(50);
    }

Setting precision takes a bit more work as well

EF6

modelBuilder.Properties<DateTime>()
  .Configure(c => c.HasColumnType("datetime2").HasPrecision(2));

EF7

foreach (var property in modelBuilder.Model.GetEntityTypes()
        .SelectMany(t => t.GetProperties())             
        )
    {
        if (property.ClrType == typeof(string) && 
          property.GetMaxLength() == null)
            property.SetMaxLength(50);

        if (property.ClrType == typeof(DateTime) )
            property.Relational().ColumnType = "datetime2(2)";

        if (property.ClrType == typeof(TimeSpan))
            property.Relational().ColumnType = "time(0)";
    }
An unhandled error has occurred. Reload 🗙