我想了解实现以下情况的正确方法的一些建议。
我有三个解决方案:使用实体框架与SQL数据库进行通信的WCF服务,托管服务的WPF服务器和使用服务的WPF客户端。我在考虑什么是实现DTO的正确方法。
目前,对于每个EF实体,我都有一个DTO,用于与客户端进行通信。因此,客户端从服务请求某些内容,服务从数据库获取信息并对其进行一些逻辑处理,然后将返回对象映射到DTO(使用AutoMapper)并发送给客户端。
在客户端,我必须为这些DTO添加一些扩展,例如,我需要添加一些自动计算的属性和方法。
我最后有两个主意
第一个想法是为我需要添加逻辑的每个DTO创建一个局部类。
我看到的优点是:我不必重写整个DTO,只需添加我需要的其他属性和方法,并且只需要映射一次EFEntity => ServiceDTO和ServiceDTO => EFEntity
缺点:我想将某些属性设置为私有,使其他属性为只读。但是无论我在Service DTO上编写的访问级别或设置器如何,它总是在客户端上生成为public .... { get; set; }
。
这是这种方法的一个例子
//AT THE WCF SERVICE: DTO
[DataContract]
public class BajaRoturaDTO
{
[DataMember] public int Id { get; set; }
[DataMember] public int NoVale { get; set; }
[DataMember] public DateTime Fecha { get; set; }
[DataMember] public UsuarioDTO Usuario { get; set; }
[DataMember] public string Comentario { get; set; }
[DataMember] public DepartamentoDTO Departamento { get; set; }
[DataMember] private List<Instance> _instances { get; set; } //I would like to make this private but it's autogenerated public on the Client
[DataContract]
public class Instance
{
[DataMember] public int ValidationState { get; set; }
[DataMember] public int Cantidad { get; set; }
[DataMember] public ProductoInstanceDTO TargetInstance { get; set; }
}
}
//AT THE WPF CLIENT: DTO PARTIAL CLASS
public partial class BajaRoturaDTO
{
public BajaRoturaDTO()
{
_instances = new List<Instance>();
}
public BajaRoturaDTO(DateTime defaultDate)
{
Fecha = defaultDate;
_instances = new List<Instance>();
}
[Magic] public List<Instance> Instances { get => new List<Instance>(_instances); }
[Magic] public decimal ImporteCosto { get => _instances.Sum(x => x.ImporteVenta); }
[Magic] public decimal ImporteVenta { get => _instances.Sum(x => x.ImporteCosto); }
[Magic] public string TotalProductos { get => _instances.Count() + " producto(s)"; }
public partial class Instance
{
[Magic] public decimal ImporteCosto { get => Cantidad * TargetInstance.Producto.PrecioCosto; }
[Magic] public decimal ImporteVenta { get => Cantidad * TargetInstance.Producto.PrecioVenta; }
public async Task Validate(DateTime targetDate)
{
ValidationState = await TargetInstance.Validate(targetDate, Cantidad);
}
}
//METHODS
public async Task AddInstance(Instance target)
{
var matchInList = _instances.FirstOrDefault(x =>
x.TargetInstance.Producto.Id == target.TargetInstance.Producto.Id
&& x.TargetInstance.Departamento.Id == target.TargetInstance.Departamento.Id);
if (matchInList is null)
{
_instances.Add(target);
await target.Validate(Fecha);
}
else
{
matchInList.Cantidad += target.Cantidad;
await matchInList.Validate(Fecha);
}
RaisePropertyChanged("Instances");
RaisePropertyChanged("ImporteCosto");
RaisePropertyChanged("ImporteVenta");
RaisePropertyChanged("TotalProductos");
}
//More methods
PD:[Magic]
装饰器是我安装的用于自动化INotifyPropertyChange
的扩展。
另一个想法是为WPF客户端上的每个DTO创建一个全新的类,并再次使用AutoMapper从ServiceDTO映射到ClientClass
我看到的优势:我可以定义自动计算的属性,私有字段,方法以及我想要的一切
缺点,我发现:我必须再次重新创建每个DTO并执行更多映射(EFEntity => ServiceDTO => CientClass和ClientClass => ServiceDTO => EFEntity)
对于您对这两种方法的看法或是否有更好的方法,我需要您的意见。
感谢您的时间,如果我有一些拼写错误,请原谅我的英语