Created
August 13, 2023 21:21
-
-
Save mortezadalil/e8d4a0f513c8a6bdc880a703a793eee9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Defining a Shadow Property | |
public class ApplicationDbContext : DbContext | |
{ | |
public DbSet<Book> Books { get; set; } | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
modelBuilder.Entity<Book>().Property<DateTime>("ModifiedDate"); | |
} | |
} | |
public class Book | |
{ | |
public int Id { get; set; } | |
public string Title { get; set; } | |
} | |
// Using Shadow Properties in a Query | |
using (var context = new ApplicationDbContext()) | |
{ | |
var books = context.Books | |
.OrderByDescending(b => EF.Property<DateTime>(b, "ModifiedDate")) | |
.ToList(); | |
} | |
//======================================================= | |
// Implementing TPH Inheritance | |
public abstract class Employee | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
} | |
public class FullTimeEmployee : Employee | |
{ | |
public decimal Salary { get; set; } | |
} | |
public class PartTimeEmployee : Employee | |
{ | |
public decimal HourlyRate { get; set; } | |
} | |
// Configure DbContext | |
public class ApplicationDbContext : DbContext | |
{ | |
public DbSet<Employee> Employees { get; set; } | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
modelBuilder.Entity<FullTimeEmployee>(); | |
modelBuilder.Entity<PartTimeEmployee>(); | |
} | |
} | |
// Querying TPH Inheritance | |
using (var context = new ApplicationDbContext()) | |
{ | |
// Returns a list of Employee objects (FullTimeEmployee and PartTimeEmployee instances) | |
var employees = context.Employees.ToList(); | |
} | |
using (var context = new ApplicationDbContext()) | |
{ | |
var fullTimeEmployees = context.Employees.OfType<FullTimeEmployee>().ToList(); | |
var partTimeEmployees = context.Employees.OfType<PartTimeEmployee>().ToList(); | |
} | |
//======================================================= | |
// Eager Loading with Projections | |
public class Blog | |
{ | |
public int Id { get; set; } | |
public string Title { get; set; } | |
public ICollection<Post> Posts { get; set; } | |
} | |
public class Post | |
{ | |
public int Id { get; set; } | |
public string Title { get; set; } | |
public int BlogId { get; set; } | |
public Blog Blog { get; set; } | |
} | |
public class BlogWithPostTitles | |
{ | |
public string BlogTitle { get; set; } | |
public List<string> PostTitles { get; set; } | |
} | |
using (var context = new ApplicationDbContext()) | |
{ | |
var blogsWithPostTitles = context.Blogs | |
.Select(b => new BlogWithPostTitles | |
{ | |
BlogTitle = b.Title, | |
PostTitles = b.Posts.Select(p => p.Title).ToList() | |
}) | |
.ToList(); | |
} | |
//======================================================= | |
// Batch Operations | |
// Install-Package EFCore.BulkExtensions | |
public class Product | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public decimal Price { get; set; } | |
} | |
Instead of inserting each Product individually, you can use the BulkInsert method to perform a batch operation: | |
using (var context = new ApplicationDbContext()) | |
{ | |
// Assume this method returns a list of products | |
List<Product> products = GetProducts(); | |
context.BulkInsert(products); | |
} | |
//======================================================= | |
// Lazy Loading | |
// Install-Package Microsoft.EntityFrameworkCore.Proxies | |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) | |
{ | |
optionsBuilder | |
.UseLazyLoadingProxies() | |
.UseSqlServer("your_connection_string"); | |
} | |
public class Author | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public virtual ICollection<Book> Books { get; set; } | |
} | |
public class Book | |
{ | |
public int Id { get; set; } | |
public string Title { get; set; } | |
public virtual Author Author { get; set; } | |
} | |
//======================================================= | |
// Powerful Custom Conventions | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
foreach (var entityType in modelBuilder.Model.GetEntityTypes()) | |
{ | |
// Set table names to uppercase | |
entityType.SetTableName(entityType.GetTableName().ToUpper()); | |
// Set column names to lowercase | |
foreach (var property in entityType.GetProperties()) | |
{ | |
property.SetColumnName(property.GetColumnName().ToLower()); | |
} | |
} | |
} | |
//======================================================= | |
// Event Listeners for Tracing and Logging | |
public class SqlQueryLoggingListener : IDiagnosticsLogger<DbLoggerCategory.Query> | |
{ | |
public bool IsEnabled(LogLevel logLevel) => logLevel == LogLevel.Information; | |
public void Log<TState>(LogLevel logLevel, DbLoggerCategory.Query eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) | |
{ | |
if (IsEnabled(logLevel)) | |
{ | |
Console.WriteLine(formatter(state, exception)); | |
} | |
} | |
} | |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) | |
{ | |
optionsBuilder | |
.UseSqlServer(connectionString) | |
.AddInterceptors(new SqlQueryLoggingListener()); | |
} | |
//======================================================= | |
// Optimizing Data Seeding | |
protected override void Up(MigrationBuilder migrationBuilder) | |
{ | |
migrationBuilder.InsertData( | |
table: "MyTable", | |
columns: new[] { "Id", "Name" }, | |
values: new object[] { 1, "My First Seed Data" }); | |
} | |
//Using Bulk Inserts for Large Data Sets | |
using EFCore.BulkExtensions; | |
using MyProject.Data; | |
using (var context = new MyDbContext()) | |
{ | |
var data = new List<MyEntity> | |
{ | |
new MyEntity { Id = 1, Name = "Data 1" }, | |
// ... | |
new MyEntity { Id = 1000, Name = "Data 1000" } | |
}; | |
context.BulkInsert(data); | |
} | |
//Applying Conditional Seeding | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
#if DEBUG | |
modelBuilder.Entity<MyEntity>().HasData( | |
new MyEntity { Id = 1, Name = "Seed Data for Debug" }); | |
#endif | |
} | |
//======================================================= | |
//Efficiently Mapping Complex Types | |
//Using Owned Entity Types | |
public class Customer | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public Address Address { get; set; } | |
} | |
public class Address | |
{ | |
public string Street { get; set; } | |
public string City { get; set; } | |
public string ZipCode { get; set; } | |
} | |
public class MyDbContext : DbContext | |
{ | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
modelBuilder.Entity<Customer>().OwnsOne(c => c.Address); | |
} | |
} | |
//Using Value Converters | |
public class Product | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public List<string> Tags { get; set; } | |
} | |
public class MyDbContext : DbContext | |
{ | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
modelBuilder.Entity<Product>() | |
.Property(p => p.Tags) | |
.HasConversion( | |
v => JsonConvert.SerializeObject(v), | |
v => JsonConvert.DeserializeObject<List<string>>(v)); | |
} | |
} | |
//Using Custom Mappings | |
public class Order | |
{ | |
public int Id { get; set; } | |
public string CustomerName { get; set; } | |
public decimal Total { get; set; } | |
public Money Currency { get; set; } | |
} | |
public class Money | |
{ | |
public decimal Amount { get; set; } | |
public string CurrencyCode { get; set; } | |
} | |
public class MyDbContext : DbContext | |
{ | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
modelBuilder.Entity<Order>() | |
.Property(o => o.Currency.Amount) | |
.HasColumnName("TotalAmount"); | |
modelBuilder.Entity<Order>() | |
.Property(o => o.Currency.CurrencyCode) | |
.HasColumnName("CurrencyCode"); | |
} | |
} | |
//======================================================= | |
//Custom Entity Materialization | |
public class Product | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public decimal Price { get; set; } | |
// Custom constructor for materialization | |
public Product(int id, string name, decimal price) | |
{ | |
Id = id; | |
Name = name; | |
Price = ApplyDiscount(price); | |
} | |
private decimal ApplyDiscount(decimal price) | |
{ | |
// Apply a custom discount based on the price | |
return price * 0.9m; | |
} | |
} | |
using (var context = new MyDbContext()) | |
{ | |
var products = context.Products | |
.FromSqlRaw("SELECT Id, Name, Price FROM Products") | |
.ToList(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment