• EF 6 新特性六


    介绍

    接下来我将给大家重点介绍一下.Net 6 之后的一些新的变更,文章都是来自于外国大佬的文章,我这边进行一个翻译,并加上一些自己的理解和解释。

    源作者链接:https://blog.okyrylchuk.dev/entity-framework-core-6-features-part-2

    正文

    没有依赖注入的 DbContext 池化

    在 EF Core 6.0 中,您可以使用DbContext池而无需依赖注入。PooledDbContextFactory类型已公开。该池是使用DbContextOptions的实例创建的,该实例将用于创建上下文实例。

    var options = new DbContextOptionsBuilder<ExampleContext>()
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCore6Playground")
        .Options;
    
    var factory = new PooledDbContextFactory<ExampleContext>(options);
    
    using var context1 = factory.CreateDbContext();
    Console.WriteLine($"Created DbContext with ID {context1.ContextId}");
    // Output: Created DbContext with ID e49db9b7-a0b0-4b54-8d0d-2cbd6c4cece7:1
    
    using var context2 = factory.CreateDbContext();
    Console.WriteLine($"Created DbContext with ID {context2.ContextId}");
    // Output: Created DbContext with ID b5a35bcb-270d-40f1-b668-5f76da1f35ad:1
    
    class ExampleContext : DbContext
    {
        public ExampleContext(DbContextOptions<ExampleContext> options)
            : base(options)
        {
        }
    }
    
    

    命令源枚举

    在 EF Core 6.0 中,新的枚举CommandSource已添加到CommandEventData类型,提供给诊断源和拦截器。枚举值指示 EF 的哪个部分创建命令。

    在 Db 命令拦截器中使用CommandSource :

    class ExampleInterceptor : DbCommandInterceptor
    {
        public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command,
            CommandEventData eventData, InterceptionResult<DbDataReader> result)
        {
            if (eventData.CommandSource == CommandSource.SaveChanges)
            {
                Console.WriteLine($"Saving changes for {eventData.Context.GetType().Name}:");
                Console.WriteLine();
                Console.WriteLine(command.CommandText);
            }
    
            if (eventData.CommandSource == CommandSource.FromSqlQuery)
            {
                Console.WriteLine($"From Sql query for {eventData.Context.GetType().Name}:");
                Console.WriteLine();
                Console.WriteLine(command.CommandText);
            }
    
            return result;
        }
    }
    
    

    数据库上下文:

    class ExampleContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options
            .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCore6CommandSource")
            .AddInterceptors(new ExampleInterceptor());
    }
    class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
    
    

    程序:

    using var context = new ExampleContext();
    
    context.Products.Add(new Product { Name = "Laptop", Price = 1000 });
    context.SaveChanges();
    
    var product = context.Products
        .FromSqlRaw("SELECT * FROM dbo.Products")
        .ToList();
    
    /* Output:
    Saving changes for ExampleContext:
    
    SET NOCOUNT ON;
    INSERT INTO[Products] ([Name], [Price])
    VALUES(@p0, @p1);
    SELECT[Id]
    FROM[Products]
    WHERE @@ROWCOUNT = 1 AND[Id] = scope_identity();
    
    
    From Sql query for ExampleContext:
    
    SELECT* FROM dbo.Products
    */
    
    

    值转换器允许转换空值

    在 EF Core 6.0 中,值转换器允许转换空值。当您有一个具有未知值的枚举时,它很有用,并且它在表中表示为一个可为空的字符串列。

    public class ExampleContext : DbContext
    {
        public DbSet<Dog> Dogs { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder
                .Entity<Dog>()
                .Property(c => c.Breed)
                .HasConversion<BreedConverter>();
        }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .EnableSensitiveDataLogging()
                .LogTo(Console.WriteLine)
                .UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=EFCore6ValueConverterAllowsNulls;");
        }
    }
    public enum Breed
    {
        Unknown,
        Beagle,
        Bulldog
    }
    public class Dog
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Breed? Breed { get; set; }
    }
    public class BreedConverter : ValueConverter<Breed, string>
    {
    #pragma warning disable EF1001
        public BreedConverter()
            : base(
                v => v == Breed.Unknown ? null : v.ToString(),
                v => v == null ? Breed.Unknown : Enum.Parse<Breed>(v),
                convertsNulls: true)
        {
        }
    #pragma warning restore EF1001
    }
    
    

    但要注意,它有陷阱。详情按链接

    显式设置临时值

    在 EF Core 6.0 中,您可以在跟踪实体之前显式设置临时值。当值被标记为临时值时,EF 不会像以前那样重置它。

    using var context = new ExampleContext();
    
    Blog blog = new Blog { Id = -5 };
    context.Add(blog).Property(p => p.Id).IsTemporary = true;
    
    var post1 = new Post { Id = -1 };
    var post1IdEntry = context.Add(post1).Property(e => e.Id).IsTemporary = true;
    post1.BlogId = blog.Id;
    
    var post2 = new Post();
    var post2IdEntry = context.Add(post2).Property(e => e.Id).IsTemporary = true;
    post2.BlogId = blog.Id;
    
    Console.WriteLine($"Blog explicitly set temporary ID = {blog.Id}");
    Console.WriteLine($"Post 1 explicitly set temporary ID = {post1.Id} and FK to Blog = {post1.BlogId}");
    Console.WriteLine($"Post 2 generated temporary ID = {post2.Id} and FK to Blog = {post2.BlogId}");
    
    // Output:
    // Blog explicitly set temporary ID = -5
    // Post 1 explicitly set temporary ID = -1 and FK to Blog = -5
    // Post 2 generated temporary ID = -2147482647 and FK to Blog = -5
    
    class Blog
    {
        public int Id { get; set; }
    }
    class Post
    {
        public int Id { get; set; }
        public int BlogId { get; set; }
    }
    class ExampleContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCore6TempValues");
    }
    
    

    结语

    联系作者:加群:867095512 @MrChuJiu

    公众号

  • 相关阅读:
    测试开发之利器论战
    测试开发的战略战术
    Python日志Logging
    Android自动测试中的monkey工具使用方法
    ADB命令讲解
    学习要深入
    测试开发发展感触
    Web Service测试工具小汇
    python接口测试浅谈
    手机上app测试总结(转)
  • 原文地址:https://www.cnblogs.com/MrChuJiu/p/15838196.html
Copyright © 2020-2023  润新知