Microsoft Entity Framework Core 8 示例
微软于 2023 年 11 月发布了最新版本的 Entity Framework Core,该版本与 Entity Framework Core 7 相比有很大变化。
要查看新增内容,请查看 Microsoft 文档EF Core 8 中的新增功能以及EF Core 8 文档中的重大变更。
每次发布 Entity Framework Core 时,微软工程师都会提供代码示例。虽然这些代码示例很棒,但它们的结构并不适合开发人员在项目中学习和使用。此外,许多代码示例可能对普通开发人员没有用。话虽如此,我还是采用了微软代码示例,并以适合普通开发人员学习的方式对代码进行了结构化。
重要的
在许多项目中,大多数项目名称表示项目的目的。
示例源码:https://download.csdn.net/download/hefeng_aspnet/89935787
仅限日期仅限时间
人们期待已久的是 DateOnly 和 TimeOnly 的支持。Microsoft 提供了一些示例,但同样不是开发人员学习的结构。因此,为此提供了 Microsoft NorthWind 数据库的修改版本,Orders 表最初将日期定义为 DateTime,但没有任何日期具有时间值,因此现在将它们定义为日期。
当使用EF Power Tools进行逆向工程时,日期被定义为 DateOnly,时间被定义为 TimeOnly。
部分订单模型仅显示 DateOnly。
public partial class Orders
{
public int OrderID { get; set; }
public DateOnly OrderDate { get; set; }
public DateOnly RequiredDate { get; set; }
public DateOnly ShippedDate { get; set; }
public DateOnly DeliveredDate { get; set; }
}
仅限时间
查看项目 TimeBetweenApp
连接和日志记录(控制台项目)
为了加强学习,包括一个用于从 appsettings.json 读取统一连接并记录到文件的类项目。
DbContext 中的示例实现,其中 ConnectionString() 读取主应用程序的 appsettings.json 作为连接字符串。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.ConfigureWithFileLoggingOnly(ConnectionString());
让我们深入了解一下 ConfigureWithFileLoggingOnly。
- 使用传递的连接字符串配置 SQL-Server
- 设置用于将日志记录到调试文件夹下的新文件,其中每天都有一个新文件夹和日志文件。
public static void ConfigureWithFileLoggingOnly(this DbContextOptionsBuilder optionsBuilder, string connectionString)
{
optionsBuilder
.UseSqlServer(connectionString)
.LogTo(new DbContextToFileLogger().Log,
new[]
{
DbLoggerCategory.Database.Command.Name
},
LogLevel.Information);
}
用于日志记录的类。
public class DbContextToFileLogger
{
/// <summary>
/// Log file name
/// </summary>
private readonly string _fileName =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"LogFiles", $"{Now.Year}-{Now.Month}-{Now.Day}",
"EF_Log.txt");
/// <summary>
/// Use to override log file name and path, file must exists
/// </summary>
/// <param name="fileName"></param>
public DbContextToFileLogger(string fileName)
{
_fileName = fileName;
}
/// <summary>
/// Setup to use default file name for logging
/// </summary>
public DbContextToFileLogger()
{
var dir = Path.GetDirectoryName(_fileName);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
if (!File.Exists(_fileName))
{
using (StreamWriter w = File.AppendText(_fileName)) ;
}
}
/// <summary>
/// append message to the existing stream
/// </summary>
/// <param name="message"></param>
[DebuggerStepThrough]
public void Log(string message)
{
if (!File.Exists(_fileName))
{
File.CreateText(_fileName).Close();
}
StreamWriter streamWriter = new(_fileName, true);
streamWriter.WriteLine(message);
streamWriter.WriteLine(new string('-', 40));
streamWriter.Flush();
streamWriter.Close();
}
}
为了确保有一个日志文件夹,每个项目的项目文件都有以下内容来创建日志文件夹(如果不存在)。
<Target Name="MakeMyDir" AfterTargets="Build">
<MakeDir Directories="$(OutDir)LogFiles" />
</Target>
ASP.NET 核心
这些项目使用依赖注入进行连接,并且没有日志记录,尽管它们已准备好通过 Program.cs 中的SeriLog设置记录到控制台。
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContextPool<ShadowContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
SetupLogging.Development();
基准网
几个项目都已准备好进行基准测试。BookApp 中的示例。请注意,在每个方法中,注释掉的方法与基准测试无关,但如果不进行基准测试,开发人员就可以看到执行的每个操作的输出。
[MemoryDiagnoser]
[RankColumn,
MinColumn,
MaxColumn,
Q1Column,
Q3Column,
AllStatisticsColumn]
[JsonExporterAttribute.Full]
[GcServer(true)]
public partial class BookOperations
{
[Benchmark]
public async Task GroupBy()
{
await using var context = new BookContext();
var books = await context.Book.ToListAsync();
List<IGrouping<int, Book>> results = books
.GroupBy(book => book.Price < 10 ? 10 : (book.Price < 20 ? 20 : 30))
.OrderBy(grouping => grouping.Key)
.ToList();
//GroupNoSwitchOutput(results);
}
[Benchmark(Baseline = true)]
public async Task Switch()
{
await using var context = new BookContext();
var books = await context.Book.ToListAsync();
List<GroupSwitch> results = books
.GroupBy(book => book.Price switch
{
<= 10 => "Cheap",
> 10 and <= 20 => "Medium",
_ => "Expensive"
})
.Select(g => new GroupSwitch(g.Key, g.ToList()))
.OrderBy(ca => ca.Category)
.ToList();
//GroupWithSwitchOutput(results);
}
}
示例源码:https://download.csdn.net/download/hefeng_aspnet/89935787