امکانات جدید EF Core 6 - قسمت 1

آخرین بروز رسانی: 1400/11/09

1. Unicode Attribute

یک ویژگی جدید یونیکد در EF Core 6.0 به شما امکان می دهد یک ویژگی رشته را به یک ستون غیر یونیکد بدون تعیین مستقیم نوع پایگاه داده نگاشت کنید.
هنگامی که سیستم پایگاه داده فقط از انواع یونیکد پشتیبانی می کند، ویژگی یونیکد نادیده گرفته می شود.

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Unicode(false)]
    [MaxLength(22)]
    public string Isbn { get; set; }
}

مایگریشن

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Books",
        columns: table => new
        {
            Id = table.Column(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
            Title = table.Column(type: "nvarchar(max)", nullable: true),
            Isbn = table.Column(type: "varchar(22)", unicode: false, maxLength: 22, nullable: true)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Books", x => x.Id);
        });
}

 

2. Precision Attribute

قبل از EF Core 6.0 می‌توانستید دقت و مقیاس را با Fluent API پیکربندی کنید. اکنون می توانید این کار را با استفاده از Data Annotations با ویژگی جدید Precision نیز انجام دهید.

public class Product
{
    public int Id { get; set; }

    [Precision(precision: 10, scale: 2)]
    public decimal Price { get; set; }
}

 

3. EntityTypeConfiguration Attribute

با شروع EF Core 6.0، می توانید اتریبیوت EntityTypeConfiguration جدید را روی entity قرار دهید، بنابراین EF Core می تواند پیکربندی مناسب را پیدا کرده و از آن استفاده کند. قبل از آن، پیکربندی کلاس باید نمونه سازی می شد و از روش OnModelCreating فراخوانی می شد.

public class ProductConfiguration : IEntityTypeConfiguration
{
    public void Configure(EntityTypeBuilder builder)
    {
        builder.Property(p => p.Name).HasMaxLength(250);
        builder.Property(p => p.Price).HasPrecision(10, 2);
    }
}
[EntityTypeConfiguration(typeof(ProductConfiguration))]
public class Product
{
    public int Id { get; set; }
    public decimal Price { get; set; }
    public string Name { get; set; }
}

 

4. Column Attribute

هنگامی که از وراثت در مدل ها استفاده می کنید، نمی توانید از ترتیب ستون های EF Core پیش فرض در جداول ایجاد شده راضی نباشید. در EF Core 6.0، می‌توانید ترتیب ستون‌ها را با ColumnAttribute مشخص کنید.

همچنین، می توانید این کار را با استفاده از یک Fluent API جدید - HasColumnOrder() انجام دهید.

public class EntityBase
{
    [Column(Order = 1)]
    public int Id { get; set; }
    [Column(Order = 99)]
    public DateTime UpdatedOn { get; set; }
    [Column(Order = 98)]
    public DateTime CreatedOn { get; set; }
}
public class Person : EntityBase
{
    [Column(Order = 2)]
    public string FirstName { get; set; }
    [Column(Order = 3)]
    public string LastName { get; set; }
    public ContactInfo ContactInfo { get; set; }
}
public class Employee : Person
{
    [Column(Order = 4)]
    public string Position { get; set; }
    [Column(Order = 5)]
    public string Department { get; set; }
}
[Owned]
public class ContactInfo
{
    [Column(Order = 10)]
    public string Email { get; set; }
    [Column(Order = 11)]
    public string Phone { get; set; }
}

 

 

5. Temporal Tables

EF Core 6.0 از جداول زمانی SQL Server پشتیبانی می کند. یک جدول را می توان به عنوان یک جدول زمانی با پیش فرض های SQL Server برای جدول زمانی و تاریخچه پیکربندی کرد.

public class ExampleContext : DbContext
{
    public DbSet People { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity()
            .ToTable("People", b => b.IsTemporal());
    }
    protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TemporalTables;Trusted_Connection=True;");
}
public class Person 
{ 
    public int Id { get; set; }
    public string Name { get; set; }    
}

 

می توانید داده های تاریخی را با روش های زیر جستجو یا بازیابی کنید:

TemporalAsOf
TemporalAll
TemporalFromTo
TemporalContainedIn
TemporalContainedIn


استفاده از جداول زمانی:

using ExampleContext context = new();
context.People.Add(new() { Name = "Oleg" });
context.People.Add(new() { Name = "Steve" });
context.People.Add(new() { Name = "John" });
await context.SaveChangesAsync();

var people = await context.People.ToListAsync();
foreach (var person in people)
{
    var personEntry = context.Entry(person);
    var validFrom = personEntry.Property("PeriodStart").CurrentValue;
    var validTo = personEntry.Property("PeriodEnd").CurrentValue;
    Console.WriteLine($"Person {person.Name} valid from {validFrom} to {validTo}");
}
// Output:
// Person Oleg valid from 06-Nov-21 17:50:39 PM to 31-Dec-99 23:59:59 PM
// Person Steve valid from 06-Nov-21 17:50:39 PM to 31-Dec-99 23:59:59 PM
// Person John valid from 06-Nov-21 17:50:39 PM to 31-Dec-99 23:59:59 PM

پرس و جو از داده های تاریخی:

var oleg = await context.People.FirstAsync(x => x.Name == "Oleg");
context.People.Remove(oleg);
await context.SaveChangesAsync();
var history = context
                .People
                .TemporalAll()
                .Where(e => e.Name == "Oleg")
                .OrderBy(e => EF.Property(e, "PeriodStart"))
                .Select(
                    p => new
                    {
                        Person = p,
                        PeriodStart = EF.Property(p, "PeriodStart"),
                        PeriodEnd = EF.Property(p, "PeriodEnd")
                    })
                .ToList();
foreach (var pointInTime in history)
{
    Console.WriteLine(
        $"Person {pointInTime.Person.Name} existed from {pointInTime.PeriodStart} to {pointInTime.PeriodEnd}");
}

// Output:
// Person Oleg existed from 06-Nov-21 17:50:39 PM to 06-Nov-21 18:11:29 PM

 

بازیابی اطلاعات تاریخی:

var removedOleg = await context
    .People
    .TemporalAsOf(history.First().PeriodStart)
    .SingleAsync(e => e.Name == "Oleg");

Console.WriteLine($"Id = {removedOleg.Id}; Name = {removedOleg.Name}");
// Output:
// Id = 1; Name = Oleg

اطلاعات بیشتر در مورد جداول زمانی

 

6. Sparse Columns

EF Core 6.0 از ستون های پراکنده SQL Server پشتیبانی می کند. این می تواند هنگام استفاده از نقشه وراثت TPH (جدول در هر سلسله مراتب) مفید باشد.

public class ExampleContext : DbContext
{
    public DbSet People { get; set; }
    public DbSet Employees { get; set; }
    public DbSet Users { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity()
            .Property(e => e.Login)
            .IsSparse();

        modelBuilder
            .Entity()
            .Property(e => e.Position)
            .IsSparse();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SparseColumns;Trusted_Connection=True;");
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class User : Person
{
    public string Login { get; set; }
}
public class Employee : Person
{
    public string Position { get; set; }
}

ستون های پراکنده محدودیت هایی دارند. پیوند به مستندات

 

7. Minimal API in EF Core

EF Core 6.0 حداقل APIهای خود را دارد. روش های افزودنی جدید یک نوع DbContext را ثبت می کنند و پیکربندی ارائه دهنده پایگاه داده را در یک خط ارائه می کنند.

const string AccountKey = "[CosmosKey]";

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSqlServer(@"Server = (localdb)\mssqllocaldb; Database = MyDatabase");

// OR
builder.Services.AddSqlite("Data Source=mydatabase.db");

// OR
builder.Services.AddCosmos($"AccountEndpoint=https://localhost:8081/;AccountKey={AccountKey}", "MyDatabase");

var app = builder.Build();
app.Run();

class MyDbContext : DbContext
{ }

 

8. Migration Bundles

یک ویژگی جدید سازگار با DevOps در EF Core 6.0 - Migration Bundles. این اجازه می دهد تا یک فایل اجرایی کوچک حاوی مهاجرت ایجاد کنید. می توانید از آن در سی دی استفاده کنید. نیازی به کپی کد منبع یا نصب NET SDK (فقط زمان اجرا) نیست.

 

CLI:

dotnet ef migrations bundle --project MigrationBundles

 

Package Manager Console:

Bundle-Migration

 

اطلاعات بیشتر در مورد بسته های مهاجرت.

 

9. Pre-convention Model Configuration

EF Core 6.0 یک پیکربندی مدل قبل از کنوانسیون را معرفی می کند. این به شما امکان می دهد پیکربندی نقشه برداری را یک بار برای یک نوع مشخص مشخص کنید. به عنوان مثال، هنگام کار با اشیاء ارزشی می تواند مفید باشد.

public class ExampleContext : DbContext
{
    public DbSet People { get; set; }
    public DbSet Products { get; set; }

    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
    {
        configurationBuilder
            .Properties()
            .HaveMaxLength(500);

        configurationBuilder
            .Properties()
            .HaveConversion();

        configurationBuilder
            .Properties()
            .HavePrecision(12, 2);

        configurationBuilder
            .Properties
() .HaveConversion(); } } public class Product { public int Id { get; set; } public decimal Price { get; set; } } public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } public Address Address { get; set; } } public class Address { public string Country { get; set; } public string Street { get; set; } public string ZipCode { get; set; } } public class AddressConverter : ValueConverter<Address, string> { public AddressConverter() : base( v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null), v => JsonSerializer.Deserialize
(v, (JsonSerializerOptions)null)) { } }

 
 

10. Compiled Models

در EF Core 6.0 می توانید مدل های کامپایل شده تولید کنید. این ویژگی زمانی معنا پیدا می کند که یک مدل بزرگ دارید و راه اندازی EF Core شما کند است. می توانید این کار را با استفاده از CLI یا Package Manager Console انجام دهید.

public class ExampleContext : DbContext
{
    public DbSet People { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    { 
        options.UseModel(CompiledModelsExample.ExampleContextModel.Instance)
        options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SparseColumns;Trusted_Connection=True;"); 
    }
}
public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

 

CLI:

 dotnet ef dbcontext optimize -c ExampleContext -o CompliledModels -n CompiledModelsExample

 

Package Manager Console:

Optimize-DbContext -Context ExampleContext -OutputDir CompiledModels -Namespace CompiledModelsExample

 

اطلاعات بیشتر در مورد مدل های کامپایل شده و محدودیت های آنها.

نظر دهید

آدرس ایمیل شما منتشر نخواهد شد. فیلدهای الزامی علامت گذاری شده اند *