关于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 企业版,主要作用是自动跟踪表的历史状态,也就是对表中的数据创建一个历史记录,非常适合追踪数据和恢复数据,
简单来说如果我们将表设置为时态表,那么就会创建两个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