C# IQueryable与Automapper:参数类型不匹配(仅在投影上?)

C# IQueryable与Automapper:参数类型不匹配(仅在投影上?),c#,odata,automapper,C#,Odata,Automapper,所以我一直在阅读文档和相关的So帖子,但我似乎找不到我想要的答案,可能是因为我不清楚预测应该如何工作 我想通过OData查询一个实体和一个DTO,如下所示: 实体 /// <summary> /// Entity maintaining the state of a scheduled task. /// </summary> public class ScheduledTask : ISoftDeletable, IAuditable { /// <sum

所以我一直在阅读文档和相关的So帖子,但我似乎找不到我想要的答案,可能是因为我不清楚预测应该如何工作

我想通过OData查询一个实体和一个DTO,如下所示:

实体

/// <summary>
/// Entity maintaining the state of a scheduled task.
/// </summary>
public class ScheduledTask : ISoftDeletable, IAuditable
{
    /// <summary>
    /// Gets or sets the unique identifier of the entity.
    /// </summary>
    [Key]
    public Guid Id { get; set; }

    /// <summary>
    /// Gets or sets the optional reference to a customer-specific task, which can be used
    /// for qualified searches against the database.  A null value here represents a "system"
    /// task that is not associated with any customer (not a usual case).
    /// </summary>
    public Guid? CustomerId { get; set; }

    /// <summary>
    /// The name of the scheduled task.  This is unique per customer.
    /// </summary>
    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    /// <summary>
    /// Gets or sets an optional description of the scheduled task.
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// All scheduled tasks are to invoke an API endpoint.  Gets or sets the endpoint.
    /// </summary>
    [Required]
    [StringLength(255)]
    [DataType(DataType.Url)]
    public string Url { get; set; }

    /// <summary>
    /// Gets or sets the HTTP Method (GET, POST, PUT, PATCH, DELETE) of the <see cref="Url"/> to invoke.
    /// </summary>
    [StringLength(30)]
    public string Method { get; set; } = "GET";

    /// <summary>
    /// If the <see cref="Method"/> for the endpoint is POST, PUT, PATCH, etc, it may include a payload in the body
    /// of the invocation.  This property gets or sets the JSON-serialized payload that will be sent to the endpoint.
    /// </summary>
    public string SerializedPayload { get; set; }

    /// <summary>
    /// If set, includes the "On-Behalf-Of" header with the HTTP message.
    /// </summary>
    [StringLength(255)]
    public string OnBehalfOf { get; set; }

    /// <summary>
    /// Gets or sets the timestamp that the endpoint is to be invoked.
    /// </summary>
    public DateTimeOffset ScheduledExecutionTimestamp { get; set; }

    /// <summary>
    /// If the Recurrence Pattern is set to something other than <see cref="RecurrencePattern.NotRecurring"/>, the task will
    /// repeat execution per the described pattern, starting from the <see cref="ScheduledExecutionTimestamp"/>.  Default value
    /// is <see cref="RecurrencePattern.NotRecurring"/>
    /// </summary>
    [Required]
    public RecurrencePattern RecurrencePattern { get; set; }

    /// <summary>
    /// Gets or sets the Enabled state of the recurring task.  If the task is disabled, it will not invoke the specified
    /// endpoint.
    /// </summary>
    [Required]
    public bool IsEnabled { get; set; } = true;

    public virtual IList<TaskTag> Tags { get; set; }
    public DateTimeOffset? DeletedDate { get; set; }
    public DateTime CreatedUtcTimestamp { get; set; } 

    [StringLength(255)]
    public string LastModifiedBy { get; set; } 
    public DateTime LastModifiedUtcTimestamp { get; set; }
}

/// <summary>
/// A categorization/ organization mechanism for <see cref="ScheduledTask"/> objects. 0..n tags can be
/// associated with any scheduled task.
/// </summary>
public class TaskTag : IAuditable
{
    /// <summary>
    /// Unique identifier of the tag
    /// </summary>
    [Key]
    public Guid Id { get; set; }

    /// <summary>
    /// Identifies the <see cref="ScheduledTask"/> ID associated with the tag
    /// </summary>
    [Required]
    public Guid ScheduledTaskId { get; set; }

    /// <summary>
    /// The <see cref="ScheduledTask"/> associated with the tag
    /// </summary>
    [ForeignKey(nameof(ScheduledTaskId))]
    public virtual ScheduledTask ScheduledTask { get; set; }

    /// <summary>
    /// The name of the tag.  <see cref="Name"/> and <see cref="ScheduledTaskId"/> form a
    /// unique combination.
    /// </summary>
    [Required]
    [StringLength(30)]
    public string Name { get; set; }

    /// <summary>
    /// The value of tag item, used for categorization
    /// </summary>
    [Required]
    [StringLength(50)]
    public string Value { get; set; }

    /// <inheritdoc cref="IAuditable"/>
    public DateTime CreatedUtcTimestamp { get; set; }
    /// <inheritdoc cref="IAuditable"/>
    [StringLength(255)]
    public string LastModifiedBy { get; set; }
    /// <inheritdoc cref="IAuditable"/>
    public DateTime LastModifiedUtcTimestamp { get; set; }
}
//
///维护计划任务状态的实体。
/// 
公共类ScheduledTask:ISoftDeletable、IAuditable
{
/// 
///获取或设置实体的唯一标识符。
/// 
[关键]
公共Guid Id{get;set;}
/// 
///获取或设置对特定于客户的任务的可选引用,该任务可以使用
///用于对数据库进行限定搜索。此处的空值表示“系统”
///与任何客户都没有关联的任务(不是常见情况)。
/// 
公共Guid?CustomerId{get;set;}
/// 
///计划任务的名称。每个客户都是唯一的。
/// 
[必需]
[长度(100)]
公共字符串名称{get;set;}
/// 
///获取或设置计划任务的可选描述。
/// 
公共字符串说明{get;set;}
/// 
///所有计划任务都将调用API终结点。获取或设置终结点。
/// 
[必需]
[StringLength(255)]
[数据类型(DataType.Url)]
公共字符串Url{get;set;}
/// 
///获取或设置要调用的的HTTP方法(GET、POST、PUT、PATCH、DELETE)。
/// 
[行政长官(30)]
公共字符串方法{get;set;}=“get”;
/// 
///如果端点的有效载荷为POST、PUT、PATCH等,则可能会在主体中包含有效载荷
///此属性获取或设置将发送到端点的JSON序列化负载。
/// 
公共字符串SerializedPayload{get;set;}
/// 
///如果已设置,则在HTTP消息中包含“代表”标头。
/// 
[StringLength(255)]
公共字符串OnBehalfOf{get;set;}
/// 
///获取或设置要调用终结点的时间戳。
/// 
公共DateTimeOffset ScheduledExecutionTimestamp{get;set;}
/// 
///如果将重复模式设置为其他模式,则任务将
///从.Default值开始,按照描述的模式重复执行
///是
/// 
[必需]
公共RecurrencePattern RecurrencePattern{get;set;}
/// 
///获取或设置定期任务的已启用状态。如果该任务已禁用,它将不会调用指定的
///终点。
/// 
[必需]
public bool IsEnabled{get;set;}=true;
公共虚拟IList标记{get;set;}
公共日期时间偏移量?删除日期{get;set;}
公共日期时间CreatedUtcTimestamp{get;set;}
[StringLength(255)]
公共字符串LastModifiedBy{get;set;}
公共日期时间LastModifiedUtticTimesTamp{get;set;}
}
/// 
///对象的分类/组织机制。0..n标记可以是
///与任何计划任务关联。
/// 
公共类任务标记:IAuditable
{
/// 
///标记的唯一标识符
/// 
[关键]
公共Guid Id{get;set;}
/// 
///标识与标记关联的ID
/// 
[必需]
公共Guid ScheduledTaskKid{get;set;}
/// 
///与标记关联的
/// 
[ForeignKey(姓名(ScheduledTaskKid))]
公共虚拟调度任务调度任务{get;set;}
/// 
///标签的名称。并形成一个
///独特的组合。
/// 
[必需]
[行政长官(30)]
公共字符串名称{get;set;}
/// 
///标记项的值,用于分类
/// 
[必需]
[长度(50)]
公共字符串值{get;set;}
/// 
公共日期时间CreatedUtcTimestamp{get;set;}
/// 
[StringLength(255)]
公共字符串LastModifiedBy{get;set;}
/// 
公共日期时间LastModifiedUtticTimesTamp{get;set;}
}
DTO

/// <summary>
/// A Scheduled Request is a call to a service endpoint at some point in the future.
/// All requests take the form of SOA Web API endpoints to be invoked.
/// </summary>
public class ScheduledTaskModel
{
    /// <summary>
    /// Gets or sets the unique identifier of the scheduled task.
    /// </summary>
    public Guid Id { get; set; }

    /// <summary>
    /// If there is a customer associated with this request, (something that we would
    /// like to group on), put the id value in here.
    /// </summary>
    public Guid? CustomerId { get; set; }

    /// <summary>
    /// A list of free-text metadata that can be used to categorize this scheduled
    /// request.
    /// </summary>
    public IDictionary<string, string> Tags { get; set; } = new Dictionary<string, string>();

    /// <summary>
    /// The descriptive name of the scheduled request.
    /// </summary>
    [Required, StringLength(250, MinimumLength = 8)]
    public string Name { get; set; }

    /// <summary>
    /// A (optional) more comprehensive description of the scheduled task than the descriptive name,
    /// used for business justification or execution notes.
    /// </summary>
    [StringLength(2000)]
    public string Description { get; set; }

    /// <summary>
    /// The SOA endpoint to hit, which will actually kick off the scheduled task.
    /// </summary>
    [Required, DataType(DataType.Url), StringLength(500)]
    public string Url { get; set; }

    /// <summary>
    /// Specifies the HTTP method that hitting the <see cref="Url"/> endpoint will use; default is GET, but acceptable
    /// values include POST, PATCH, PUT, and DELETE.
    /// </summary>
    [Required, StringLength(30)]
    public string Method { get; set; } = "GET";

    /// <summary>
    /// If the <see cref="Method"/> supports a payload (POST, PATCH, PUT) and this is not null,
    /// it will be included with the request.
    /// </summary>
    public object Payload { get; set; }

    /// <summary>
    /// If specified, sets the "On-Behalf-Of" header to the set value.  Useful for attributing an action
    /// to a specified user.
    /// </summary>
    [StringLength(250)]
    public string OnBehalfOf { get; set; }

    /// <summary>
    /// Gets or sets the timestamp of when the scheduled task is to be invoked.
    /// </summary>
    [Required, DataType(DataType.DateTime)]
    public DateTimeOffset ScheduledExecutionTimestamp { get; set; }

    /// <summary>
    /// Gets or sets the recurrence pattern of the scheduled task.  Default is <see cref="RecurrencePattern.NotRecurring"/>.
    /// If recurrence is set, <see cref="ScheduledExecutionTimestamp"/> will be ignored as the scheduled execution and instead
    /// be used as a template to set the recurrence.
    /// </summary>
    [DataType(DataType.Text), Display(Name="", Description = "Gets or sets the recurrence pattern of the scheduled task.  Default is 'notRecurring'.  If recurrence is set, 'ScheduledExecutionTimestamp' will be ignored as the scheduled execution and instead be used as a template to set the recurrence.")]
    public RecurrencePattern RecurrencePattern { get; set; }

    /// <summary>
    /// Gets or sets the enabled state of the scheduled task.  Default <see cref="true"/>.  A disabled task will not execute.
    /// </summary>
    public bool IsEnabled { get; set; } = true;
}
//
///计划请求是在将来某个时间点对服务端点的调用。
///所有请求都采用要调用的SOA Web API端点的形式。
/// 
公共类ScheduledTaskModel
{
/// 
///获取或设置计划任务的唯一标识符。
/// 
公共Guid Id{get;set;}
/// 
///如果有客户与此请求相关,我们会
///如要分组),请将id值放在此处。
/// 
公共Guid?CustomerId{get;set;}
/// 
///自由文本元数据列表,可用于对该计划进行分类
///请求。
/// 
公共IDictionary标记{get;set;}=new Dictionary();
/// 
///计划请求的描述性名称。
/// 
[必需,字符串长度(250,最小长度=8)]
公共字符串名称{get;set;}
/// 
///(可选)比描述性名称更全面的计划任务描述,
///用于业务论证或执行说明。
/// 
[秘书长(2000年)]
公共字符串说明{get;set;}
/// 
///要命中的SOA端点,这将实际启动计划任务。
/// 
[必需,数据类型(DataType.Url),StringLength(500)]
公共字符串Url{get;set;}
/// 
///指定命中端点将使用的HTTP方法;默认值为GET,但可以接受
///值包括POST、PATCH、PUT和DELETE。
/// 
[所需长度(30)]
公共字符串方法{get;set;}=“get”;
/// 
///如果支持有效负载(POST、PATCH、PUT),且该负载不为空,
///它将包含在请求中。
/// 
公共对象有效负载{get;set;}
/// 
///如果指定,则将“代表”标题设置为设置的值。用于指定操作的属性
///到
var configuration = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<KeyValuePair<string, string>, TaskTag>()
        .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Key))
        .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.Value));

    cfg.CreateMap<TaskTag, KeyValuePair<string, string>>().ConvertUsing((tag, context) =>
        new KeyValuePair<string, string>(tag.Name, tag.Value));

    cfg.CreateMap<ScheduledTaskModel, ScheduledTask>().ForMember(dest => dest.SerializedPayload,
        opt => opt.MapFrom(src => JsonConvert.SerializeObject(src.Payload)));

    cfg.CreateMap<ScheduledTask, ScheduledTaskModel>().ForMember(dest => dest.Payload,
        opt => opt.MapFrom(src => JsonConvert.DeserializeObject(src.SerializedPayload)));
});
public IQueryable<ScheduledTaskModel> GetScheduledTaskByCustomerId(Guid customerId)
{
    var queryable = _dbContext.ScheduledTasks.Include(x => x.Tags)
        .Where(x => x.CustomerId == customerId && x.DeletedDate == null);
    return _mapper.ProjectTo<ScheduledTaskModel>(queryable);
}