我将POCO对象投影到DTO对象时遇到了一些困难
我的POCO对象
public class LogEntry
{
public LogEntry()
{
this.Username = Environment.UserName;
this.LogNote = String.Empty;
var now = DateTime.Now;
this.LoginTime = now;
this.LastSeenInput = now;
this.ServerName = Environment.MachineName;
}
public int LogEntryId { get; set; }
[Required(AllowEmptyStrings = false)]
[Column(TypeName = "nvarchar")]
[MaxLength(64)]
public string Username { get; set; }
[Required(AllowEmptyStrings = true)]
[Column(TypeName = "varchar")]
[MaxLength(20)]
public string ServerName { get; set; }
public DateTime LoginTime { get; set; }
public TimeSpan ConnectedFor { get; set; }
public TimeSpan IdleFor { get; set; }
public DateTime? LastSeenInput { get; set; }
[Required(AllowEmptyStrings = true)]
public string LogNote { get; set; }
}
我的DTO对象
public sealed class ClientEventDTO
{
public int LogEntryId { get; set; }
public string Username { get; set; }
public string ServerName { get; set; }
public DateTime LoginTime { get; set; }
public TimeSpan ConnectedFor { get; set; }
public string LogNote { get; set; }
public TimeSpan IdleForWithLast { get; set; }
}
我想要做的是我希望IdleForWithLast
代表
public TimeSpan IdleForWithLast
{
get
{
var tmp = IdleFor;
if (LastSeenInput.HasValue)
tmp = tmp.Add(DateTime.Now - LastSeenInput.Value);
return tmp;
}
}
但是当我这样做时
static void Main(string[] args)
{
Mapper.CreateMap<LogEntry, ClientEventDTO>()
.ForMember(dto => dto.IdleFor,
a => a.MapFrom(ent => ent.LastSeenInput == null ?
ent.IdleFor :
ent.IdleFor + (DateTime.Now - ent.LastSeenInput.Value)
)
);
Mapper.AssertConfigurationIsValid();
using (var ctx = new LoginHistoryContext())
{
var username = "Scott";
var query = ctx.LogEntries.Where(entry => entry.Username == username).Project().To<ClientEventDTO>();
var result = query.ToList();
Debugger.Break();
}
}
我收到以下异常
System.ArgumentException未处理
的HResult = -2147024809
Message = DbArithmeticExpression参数必须具有数字公共类型 源= System.Data.Entity的
将ent.IdleFor + (DateTime.Now - ent.LastSeenInput.Value)
更改为ent.IdleFor.Add(DateTime.Now - ent.LastSeenInput.Value)
只会给我一个不同的例外
System.NotSupportedException未处理
的HResult = -2146233067
Message = LINQ to Entities无法识别方法'System.TimeSpan Add(System.TimeSpan)'方法,并且此方法无法转换为商店表达式。
源= System.Data.Entity的
在保持兼容性QueryableExtensions
时使用这种操作的正确方法是什么?
如果您不关心兼容性,可以通过这种方式轻松完成
static void Main(string[] args)
{
Mapper.CreateMap<LogEntry, ClientEventDTO>()
.ForMember(dto => dto.IdleFor, opt=>opt.ResolveUsing<CustomResolver>());
Mapper.AssertConfigurationIsValid();
using (var ctx = new LoginHistoryContext())
{
var username = "Scott";
var query = ctx.LogEntries.Where(entry => entry.Username == username);
var result = Mapper.Map<List<ClientEventDTO>>(query.ToList());
Debugger.Break();
}
}
public class CustomResolver : ValueResolver<LogEntry, TimeSpan>
{
protected override TimeSpan ResolveCore(LogEntry source)
{
var tmp = source.IdleFor;
if (source.LastSeenInput.HasValue)
tmp = tmp.Add(DateTime.Now - source.LastSeenInput.Value);
return tmp;
}
}
这就是我可能会在这种情况下使用的工作,但我想知道将来如何处理这个问题,以防我必须使用QueryableExtensions
并且我需要做类似的事情。
答案 0 :(得分:2)
您可以忽略此成员,并在映射后手动映射:
Mapper.CreateMap<LogEntry, ClientEventDTO>()
.ForMember(dto => dto.IdleForWithLast, m => m.Ignore())
.AfterMap((ent, dto) =>
dto.IdleForWithLast = ent.LastSeenInput.HasValue ?
ent.IdleFor + (DateTime.Now - ent.LastSeenInput.Value) : ent.IdleFor);
或者在地图后更改默认映射:
Mapper.CreateMap<LogEntry, ClientEventDTO>()
.ForMember(dto => dto.IdleForWithLast, m => m.MapFrom(ent => ent.IdleFor))
.AfterMap((ent, dto) => {
if (ent.LastSeenInput.HasValue)
dto.IdleForWithLast += DateTime.Now - ent.LastSeenInput.Value;
});