关于Entity Framework Core 6 新增特性解读

介绍

本文对前面6篇Entity Framework Core 6特性的一个详细说明

正文

EntityTypeConfiguration 属性

该属性是一个非常实用的属性,之前我们的写法都是这样,这样会存在一个问题,就是项目里面实体很多,就算根据业务进行了分类,要去找到被修改的实体也是个麻烦事。

 public static class SimulationsPartDbContextModelCreatingExtensions
    {
        public static void ConfigureSimulationsPart(
            this ModelBuilder builder,
            Action<SimulationsPartModelBuilderConfigurationOptions> optionsAction = null)
        {
            Check.NotNull(builder, nameof(builder));

            var options = new SimulationsPartModelBuilderConfigurationOptions(
                SimulationsPartDbProperties.DbTablePrefix,
                SimulationsPartDbProperties.DbSchema
            );

            optionsAction?.Invoke(options);

            builder.ApplyConfiguration(new SimulationCfg());

            builder.ApplyConfiguration(new SimulationsVersionPubCfg());

            builder.ApplyConfiguration(new SimulationsSummaryDataCfg());

            builder.ApplyConfiguration(new SimulationCommercialFormatCfg());

            builder.ApplyConfiguration(new SimulationBuildingCfg());

            builder.ApplyConfiguration(new SimulationKeyPointCfg());

            builder.ApplyConfiguration(new SimulationSubjectMapCfg());

            builder.ApplyConfiguration(new SimulationPlanIndexCfg());

			builder.ApplyConfiguration(new SimulationKeyPointExCfg());

            builder.ApplyConfiguration(new SimulationManageIndexCfg());

以后我们就将对应实体的Fluent API配置直接写在头部

[EntityTypeConfiguration(typeof(ProductConfiguration))]
public class Product
{
    public int Id { get; set; }
    public decimal Price { get; set; }
    public string Name { get; set; }
}

时态表

对于金融或财务系统的朋友应该是福音了,但是需要SqlServer 企业版,主要作用是自动跟踪表的历史状态,也就是对表中的数据创建一个历史记录,非常适合追踪数据和恢复数据,

https://docs.microsoft.com/zh-cn/sql/relational-databases/tables/temporal-tables?view=sql-server-ver15

简单来说如果我们将表设置为时态表,那么就会创建两个datetime2名为PeriodStart和的隐藏列PeriodEnd,这两个列存储的是 SQL Server 生成的 UTC 时间,时态表会创建一个关联的历史记录表.

项目中的使用环节,比如我们要查询一个商品的历史波动,先去想想你们会怎么写,或者我要一个设备的历史数据做数据分析,

查询历史数据

使用时态表我们可以这样写。查询将PeriodStart和PeriodEnd值投影到匿名类型中,以及当时实体实例的快照。该方法用于获取周期值,因为它们映射到实体中的阴影属性。

var productSnapshots = context.Products
    .TemporalBetween(from, to)
    .OrderBy(product => EF.Property<DateTime>(product, "PeriodStart"))
    .Where(product => product.Name == productName)
    .Select(product =>
        new
        {
            Product = product,
            PeriodStart = EF.Property<DateTime>(product, "PeriodStart"),
            PeriodEnd = EF.Property<DateTime>(product, "PeriodEnd")
        })
    .ToList();

查找特定的历史记录
var order = context.Orders
    .TemporalAsOf(on)
    .Include(e => e.Product)
    .Include(e => e.Customer)
    .Single(order =>
        order.Customer.Name == customerName
        && order.OrderDate > on.Date
        && order.OrderDate < on.Date.AddDays(1));


// SQL

FOR SYSTEM_TIME FROM '2022-01-24' TO '9999-12-31'  
恢复已删除的数据
// 找到被删除数据的时间搓
var customerDeletedOn = context.Customers
    .TemporalAll()
    .Where(customer => customer.Name == customerName)
    .OrderBy(customer => EF.Property<DateTime>(customer, "PeriodEnd"))
    .Select(customer => EF.Property<DateTime>(customer, "PeriodEnd"))
    .Last();

// 根据时间搓获取数据
    var customerAndOrders = context.Customers
    .TemporalAsOf(customerDeletedOn.AddMilliseconds(-1))
    .Include(e => e.Orders)
    .Single();

// 恢复数据
context.Add(customerAndOrders);
context.SaveChanges();

HasConversion

这个其实没啥特别的,做过DDD的同学应该都经历过。

public class AddressConverter : ValueConverter<Address, string>
{
    public AddressConverter()
        : base(
            v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
            v => JsonSerializer.Deserialize<Address>(v, (JsonSerializerOptions)null))
    {
    }
}

命令源枚举

这个是一个非常实用的东西,我们日常开发进行代码调试或者做一些额外配置我觉得都用得到,我看网上有用这个做读写分离的文章

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;
    }
}

结语

联系作者:加群:867095512 @MrChuJiu

公众号

posted @ 2022-01-24 15:44  初久的私房菜  阅读(241)  评论(0编辑  收藏  举报
作者:初久的私房菜
好好学习,天天向上
返回顶部小火箭
好友榜:
如果愿意,把你的博客地址放这里
张弛:https://blog.zhangchi.fun/