What is Entity Framework Core?
Entity Framework Core (EF Core) is a lightweight, extensible, and cross-platform version of Entity Framework.
EF Core introduces many improvements and new features when compared with EF6.
EF Core keeps the developer experience from EF6, and most of the top-level APIs remain the same too, so EF Core will feel very familiar to those who have used EF6.
At the same time, EF Core is a new code base and not as mature as EF6.
New features introduced in EF Core 2.1:
1. Entity types with constructors
It is now possible to define a constructor with parameters and have EF Core call this constructor when creating an instance of the entity.
The constructor parameters can be bound to mapped properties, or to various kinds of services to facilitate behaviors like lazy-loading and can be used to inject property values, lazy loading delegates, and services.
Example:
public class Employee
{
public Employee(string name, string designation)
{
Name = name;
Designation = designation;
}
[Key]
public int EmpId { get; set; }
public string Name { get; set; }
public string Designation { get; set; }
}
Some points to consider:
- Not all properties need to have constructor parameters. If a property is not set by any constructor parameter, EF Core will set it after calling the constructor in the normal way.
- The parameter types and names must match property types and names, except that properties can be Pascal-cased while the parameters are camel-cased.
- EF Core cannot set navigation properties using a constructor.
- The constructor can be public, private, or have any other accessibility.
2. Value Conversions
Value converters allow property values to be converted when reading from or writing to the database.
This conversion can be from one value to another of the same type (for example, encrypting strings) or
from a value of one type to a value of another type (for example, converting enum values to and from strings in the database.)
public class Rider
{
public int Id { get; set; }
public EquineBeast Mount { get; set; }
}
public enum EquineBeast
{
Donkey,
Mule,
Horse,
Unicorn
}
Then conversions can be defined in OnModelCreating to store the enum values as strings (for example, "Donkey", "Mule", ...) in the database:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Rider>()
.Property(e => e.Mount)
.HasConversion(
v => v.ToString(),
v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
}
Limitations:
There are a few known current limitations of the value conversion system:
- As noted above, null cannot be converted.
- There is currently no way to spread a conversion of one property to multiple columns or vice-versa.
- Use of value conversions may impact the ability of EF Core to translate expressions to SQL. A warning will be logged for such cases. Removal of these limitations is being considered for a future release.
3. Query Types
An EF Core model can now include query types. Unlike entity types, query types do not have keys defined on them and cannot be inserted, deleted or updated (that is, they are read-only), but they can be returned directly by queries. Some of the usage scenarios for query types are:
- Mapping to views without primary keys
- Mapping to tables without primary keys
- Mapping to queries defined in the model
- Serving as the return type for FromSql() queries
db.Database.ExecuteSqlCommand(
@"CREATE VIEW View_BlogPostCounts AS
SELECT Name, Count(p.PostId) as PostCount from Blogs b
JOIN Posts p on p.BlogId = b.BlogId
GROUP BY b.Name");
#region Query Type
public class BlogPostsCount
{
public string BlogName { get; set; }
public int PostCount { get; set; }
}
#endregion
4. Eager loading
Use the Include method to specify related data to be included in query results. In the following example, the blogs that are returned in the results will have their Posts property populated with the related posts.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ToList();
}
You can include related data from multiple relationships in a single query.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.Include(blog => blog.Owner)
.ToList();
}
You can drill down through relationships to include multiple levels of related data using the ThenInclude method. The following example loads all blogs, their related posts, and the author of each post.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
}
Top comments (2)
Great post.
Thank you!