Melbourne, Australia
02 September 2018
Note: At moment of writing I am using EFCore 2.1.1
I like learning when I am doing practical tasks, then I can dive into the problem and fully understand differences between version of frameworks. Also as a developer I have pet project :) I started it more than 5 years and still doing it why? Well because I am learning and I don’t believe that I can be good without those projects. Because at work I try to be practical while at my project I can do as I wish and learn how to do and how to not.
So for long time I did wanted to upgrade my project to latest tech and finally few weeks ago I’ve done it and I want to share what I’ve learned
First I think that Microsoft messed up with names. Core does not mean that it must be compiled with .net core. But good news that you can include it in you projects where you can use .net core because of some legacy. Entityframework Core is compiled with .NETStandard means that you can reference it in .Net Framework 4.6.2 and up. So this is my case because I still have few librarries which are not yet .NetStandard ready.
I started my Upgrade with article from Microsoft which says well remove old libraries and add new. I did but it wasn’t so easy in the end.
base("name=mydbentities")-> YourContextContext(DbContextOptions options) : base(options)
In old (let me call like that) EF we used to have constructor with string now it accepts DbContextOptions
OnModelCreating(DbModelBuilder modelBuilder) -> OnModelCreating(ModelBuilder modelBuilder)
Change is very minor so class name changed names
If you are using SqlQuery in EF then its bit of a trouble, because there is no direct replacement for this method. There are some manual steps to be done. Firstly need to register View in OnModelCreating More info can be found at github issue
In EF I used to create many to many by adding collection property on both classes. For instance
public class Category{
......
public ICollection<DancerClass> Classes{get;set;}
......
}
public class DancerClass{
......
public ICollection<Category> Categories{get;set;}
......
}
This is not supported in EFCore you will need to modify to be
public class CategoryToDancerClass
{
public DancerClass DancerClass { get; set; }
public Category Category { get; set; }
public int DancerClass_Id { get; set; }
public int Category_Id { get; set; }
}
public class Category{
......
public ICollection<CategoryToDancerClass> Classes{get;set;}
......
}
public class DancerClass{
......
public ICollection<CategoryToDancerClass> Categories{get;set;}
......
}
Also you will need to provide information OnModel
modelBuilder.Entity<CategoryToDancerClass>()
.ToTable("DancerClassCategories")
.HasKey(sc => new { sc.DancerClass_Id, sc.Category_Id});
modelBuilder.Entity<CategoryToDancerClass>()
.HasOne(sc => sc.DancerClass)
.WithMany(s => s.Categories)
.HasForeignKey(sc => sc.DancerClass_Id);
modelBuilder.Entity<CategoryToDancerClass>()
.HasOne(sc => sc.Category)
.WithMany(s => s.DancerClasses)
.HasForeignKey(sc => sc.Category_Id);
So if you are planning upgrade this would be good point to go via all of you classes and modify in old code base to have less issues later.
public virtual Dancer GetForEdit(int id)
{
return _db.Dancers
.Include(d => d.Classes)
.Include(d => d.Classes.Select(c => c.DancerClass))
.Include(d => d.Classes.Select(c => c.ProgramType))
.Include(d => d.Organisations)
.AsNoTracking()
.FirstOrDefault(i => i.Id == id);
}
Will become in core
public virtual Dancer GetForEdit(int id)
{
return _db.Dancers
.Include(d => d.Classes)
.Include(d => d.Classes).ThenInclude(c => c.DancerClass)
.Include(d => d.Classes).ThenInclude(c => c.ProgramType)
.Include(d => d.Organisations)
.AsNoTracking()
.FirstOrDefault(i => i.Id == id);
}
Only in EFCore 2.1 lazy loading was implemented. To implement lazy loading there is two ways.
Microsoft.EntityFrameworkCore.Proxies
, but there is feature request because now to use lazy loading all navigation properties must be virtual
. There is github issue with feature request.