Skip to content

Instantly share code, notes, and snippets.

@NMillard
Last active January 18, 2020 15:34
Show Gist options
  • Select an option

  • Save NMillard/3890911edcf16b7020e5e3871e4a263a to your computer and use it in GitHub Desktop.

Select an option

Save NMillard/3890911edcf16b7020e5e3871e4a263a to your computer and use it in GitHub Desktop.
EntityFramework examples
using EFPractice.DataLayer.Interfaces;
using EFPractice.Domain;
using Microsoft.EntityFrameworkCore;
namespace EFPractice.DataLayer {
internal class ApplicationContext : DbContext, IDataStore {
public ApplicationContext(DbContextOptions options) : base(options) {}
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApplicationContext).Assembly);
}
}
}
using System;
using System.Collections.Generic;
namespace EFPractice.Domain {
/// <summary>
/// Better approach with encapsulated fields
/// </summary>
public class Author {
private string id;
private readonly List<Book> books;
public Author(string name) {
id = Guid.NewGuid().ToString("D");
books = new List<Book>();
Name = name;
}
public string Name { get; private set; }
public RecommendationScore RecommendationScore { get; private set; }
public AuthorStatus Status { get; private set; }
public IReadOnlyList<Book> Books => books;
}
}
using System;
using EFPractice.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace EFPractice.DataLayer.Configurations {
public class AuthorConfig : IEntityTypeConfiguration<Author> {
public void Configure(EntityTypeBuilder<Author> builder) {
builder.ToTable("Authors");
builder.HasKey("id")
.HasName("PK_Authors"); // Name of the primary key in the database (ie. NOT the column name)
builder.Property(author => author.Name)
.HasMaxLength(150) // setting max length will provide huge performance gains
.IsRequired();
builder.Metadata
.FindNavigation(nameof(Author.Books))
.SetPropertyAccessMode(PropertyAccessMode.Field); // Convention based -> will find field named books
builder.Property(author => author.Status)
.HasConversion(
value => value.ToString(), // How to convert when storing
convertedValue => Enum.Parse<AuthorStatus>(convertedValue)); // How to convert value from database when retrieving
builder.OwnsOne<RecommendationScore>(nameof(Author.RecommendationScore), recommendationBuilder => {
recommendationBuilder.Property(nameof(RecommendationScore.Score))
.HasField("score");
});
}
}
}
namespace EFPractice.Domain {
public enum AuthorStatus {
Approved,
Pending,
Banned,
}
}
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFPractice.Domain {
/// <summary>
/// Extreme case of a poorly designed class
/// </summary>
[Table("Books")]
public class BadBook {
public BadBook() {
// Never have constructors that leave your objects in an invalid state.
// Especially when it's just to please an external framework...
}
public BadBook(string name, DateTime released) {
Name = name;
Released = released;
}
[Key]
public int Id { get; set; }
[Required(ErrorMessage = "Book name is required")]
[MaxLength(150)]
public string Name { get; set; }
[DataType("DateTime2")]
public DateTime Released { get; set; }
[Required]
[ForeignKey("AuthorId")]
public Author Author { get; set; }
public string AuthorId { get; set; }
}
}
using System;
namespace EFPractice.Domain {
public class Book {
private string id;
public Book(string name) {
id = Guid.NewGuid().ToString("D");
Name = name;
}
public string Name { get; private set; }
public DateTime Released { get; private set; }
public Author Author { get; private set; }
}
}
using EFPractice.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace EFPractice.DataLayer.Configurations {
public class BookConfig : IEntityTypeConfiguration<Book> {
public void Configure(EntityTypeBuilder<Book> builder) {
builder.ToTable("Books");
builder.HasKey("id");
builder.Property(book => book.Name).HasMaxLength(150).IsRequired();
builder.Property(book => book.Released).IsRequired();
builder.HasOne(book => book.Author)
.WithMany(author => author.Books)
.HasForeignKey("AuthorId")
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace EFPractice.DataLayer.Extensions {
public static class AddApplicationDbContext {
public static IServiceCollection AddBookStoreDbContext(this IServiceCollection services, string connectionString) {
services.AddDbContext<ApplicationContext>(builder => {
builder.UseSqlServer(connectionString);
});
return services;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment