使用OData v4,EF6和Web API v2.2处理日期

Tim*_*Tim 7 entity-framework odata asp.net-web-api asp.net-web-api2

我正处于从v1-3升级到v4的过程中,但我遇到了一些问题.

我的理解是DateTime不受支持,我必须始终使用DateTimeOffset.精细.

但在我date在DateTime中存储Sql 数据类型之前,现在看来我得到了这个错误:

Member Mapping specified is not valid. The type 'Edm.DateTimeOffset[Nullable=False,DefaultValue=,Precision=]' of member 'CreatedDate' in type 'MyEntity' is not compatible with 'SqlServer.date[Nullable=False,DefaultValue=,Precision=0]'
Run Code Online (Sandbox Code Playgroud)

这有什么用?我需要能够在数据库中专门存储日期(时间和地点并不重要).如果我能得到Edm.Date以及返回的数据类型会很棒,但我之前没有.

谢谢.

编辑:示例类

之前:

public class Ticket
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required, MaxLength(50)]
    public string Reference { get; set; }

    [Column(TypeName = "date")]
    public DateTime LoggedDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

后:

public class Ticket
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required, MaxLength(50)]
    public string Reference { get; set; }

    [Column(TypeName = "date")]
    public DateTimeOffset LoggedDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这在EF中无效.

Tan*_*nfu 11

一种选择是在实体中定义新属性.说标题映射到EF:

public partial class Title
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Nullable<System.DateTime> CreatedOn { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后添加DateTimeOffset的新属性:

public partial class Title
{
    [NotMapped]
    public DateTimeOffset? EdmCreatedOn
    {
        // Assume the CreateOn property stores UTC time.
        get
        {
            return CreatedOn.HasValue ? new DateTimeOffset(CreatedOn.Value, TimeSpan.FromHours(0)) : (DateTimeOffset?)null;
        }
        set
        {
            CreatedOn = value.HasValue ? value.Value.UtcDateTime : (DateTime?)null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并且生成OData模型的代码如下所示:

    public static IEdmModel GetModel()
    {
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        EntityTypeConfiguration<Title> titleType= builder.EntityType<Title>();
        titleType.Ignore(t => t.CreatedOn);
        titleType.Property(t => t.EdmCreatedOn).Name = "CreatedOn";

        builder.EntitySet<Title>("Titles");

        builder.Namespace = typeof(Title).Namespace;

        return builder.GetEdmModel();
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器看起来像:

public class TitlesController : ODataController
{
    CustomerManagementSystemEntities entities = new CustomerManagementSystemEntities();

    [EnableQuery(PageSize = 10, MaxExpansionDepth = 5)]
    public IHttpActionResult Get()
    {
        IQueryable<Title> titles = entities.Titles;
        return Ok(titles);
    }

    public IHttpActionResult Post(Title title)
    {
        entities.Titles.Add(title);
        return Created(title);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,您应该使用此代码获得运行时错误.运行时将为Nullable <System.DateTime>或DateTime?的任何实体属性提供错误.如果忽略ODataConventionModelBuilder配置级别的属性,则无关紧要.至少这就是我得到的. (3认同)

Tim*_*Tim 4

对于将来遇到此问题的任何人,OData v4 团队已经修复了此问题。

[Column(TypeName = "date")]
public DateTime Birthday { get; set; }
Run Code Online (Sandbox Code Playgroud)

现在将自动解析为 Edm.Date。

如果您像我一样并且按照惯例进行date类型处理,则必须手动将属性声明为日期,以免它们被自动解析为 DateTimeOffset。OData 目前不允许您添加自己的约定。

customer.Property(c => c.Birthday).AsDate();
Run Code Online (Sandbox Code Playgroud)

http://odata.github.io/WebApi/#12-01-DateAndTimeOfDayWithEF