因此,我正在尝试为新的 .NET 应用程序设置所有基础知识。这是一个 Blazor 应用程序,使用干净的架构和代码优先的 EF Core 创建。
在我的域层中,我定义了一些实体,这些实体将被 EF Core 用于生成数据库。在演示/WebUI 层中,我创建了一个模型文件夹,可以将其提供给 razor 文件。最初的想法是在检索数据时直接从实体映射到模型。
当在应用程序层中为我的服务创建接口时,我意识到应用程序层不应该访问表示层。因此我无法拥有像
Task<SomeModel> GetSomeModelByIdAsync(int id);
这样的界面。我必须返回该实体,但我不希望它一直发送到外层,对吗?
处理这个问题的正确方法是什么?我应该将模型移至应用程序层,还是创建表示层可以映射到模型的 DTO?这只是一个业余爱好项目,所以我可以慢慢来,把事情做得比应有的更好。是的,我可能想太多了,否则还有什么乐趣呢?
一般来说,您应该首先根据您的应用程序需求设计您的核心域实体。 如果以天气预报为例,我们可以这样定义它。 使用 Guid 作为记录 Id 并使用小数作为温度是原始的痴迷,应该避免。 不要让您的数据存储决定您的应用程序设计。
public sealed record DmoWeatherForecast
{
public WeatherForecastId WeatherForecastId { get; init; } = WeatherForecastId.NewEntity;
public DateOnly Date { get; init; }
public Temperature Temperature { get; set; } = new(0);
public string? Summary { get; set; }
}
哪里
WeatherForecastId
是:
public readonly record struct WeatherForecastId
{
public Guid Value { get; init; }
public object KeyValue => this.Value;
public WeatherForecastId(Guid value)
=> this.Value = value;
public static WeatherForecastId NewEntity
=> new(Guid.Empty);
}
并且
Temperature
是:
public record Temperature
{
public decimal TemperatureC { get; init; }
public decimal TemperatureF => 32 + (this.TemperatureC / 0.5556m);
public Temperature() { }
public Temperature(decimal temperature)
{
this.TemperatureC = temperature;
}
}
在基础设施层,我们需要依靠原语来适应数据存储:
public sealed record DboWeatherForecast
{
[Key] public Guid WeatherForecastID { get; init; } = Guid.Empty;
public DateTime Date { get; init; }
public decimal Temperature { get; set; }
public string? Summary { get; set; }
}
还有一个映射类:
public sealed class DboWeatherForecastMap : IDboEntityMap<DboWeatherForecast, DmoWeatherForecast>
{
public DmoWeatherForecast MapTo(DboWeatherForecast item)
=> Map(item);
public DboWeatherForecast MapTo(DmoWeatherForecast item)
=> Map(item);
public static DmoWeatherForecast Map(DboWeatherForecast item)
=> new()
{
WeatherForecastId = new(item.WeatherForecastID),
Date = DateOnly.FromDateTime(item.Date),
Temperature = new(item.Temperature),
Summary = item.Summary
};
public static DboWeatherForecast Map(DmoWeatherForecast item)
=> new()
{
WeatherForecastID = item.WeatherForecastId.Value,
Date = item.Date.ToDateTime(TimeOnly.MinValue),
Temperature = item.Temperature.TemperatureC,
Summary = item.Summary
};
}
您可以在此处查看完整的实现:https://github.com/ShaunCurtis/Blazr.Demo
以及简单的发票复杂对象实现。