Dot-Net

如何讓 Web API OData v4 使用 DateTime

  • August 7, 2014

我有一個相當大的數據模型,我想使用 OData V4 協議使用 Web API OData 公開它。

基礎數據儲存在 SQL Server 2012 數據庫中。該數據庫中有許多 DateTime 列。

當我連接它時,我收到一個錯誤,即 System.DateTime 不受支持。

所以這是我的問題,我該怎麼做才能在 OData 提要中看到我的 DateTime 列?

注意:我無法返回並將所有列更改為 DateTimeOffset 列。

我嘗試更改實體框架 edmx 中列的類型,但它給了我這個錯誤:

指定的成員映射無效。‘MyProject.MyEntity’ 類型中成員 ‘MyPropertyHere’ 的類型 ‘Edm.DateTimeOffset[Nullable=False,DefaultValue=,Precision=]’ 與 ‘SqlServer.datetime[Nullable=False,DefaultValue=,Precision=3] 不兼容’MyDataModel.Store.MyEntity’ 類型中的成員 ‘MyColumnName’。

(基本上認為 DateTime 與 DateTimeOffset 不兼容。)

Web API OData 團隊真的忽略了所有需要使用 SQL Server 類型的人DateTime嗎?

更新:我找到了解決方法,但它們需要更新 EF 模型才能工作。如果可以避免的話,我寧願不必單獨更新數百個屬性。

**更新:這個問題讓我意識到微軟管理其 OData 產品的方式存在嚴重缺陷。有很多問題,但這個是最明顯的。Web API OData 中有大量缺失的功能。 *插入的事務*和排序是其中的兩個。這兩個項目(在 OData 規範中並且在微軟殺死它之前在 WCF 數據服務中)對於任何實際系統都至關重要。

但是,他們沒有將時間花在那些缺少 OData 規範中的功能的關鍵點上,而是決定花時間刪除對許多開發人員非常有幫助的功能。它集中體現了糟糕的管理,優先考慮刪除工作功能而不是添加急需的功能。

我嘗試與 Web API OData 代表討論這些問題,最後,我打開了一個問題/票證,幾天后又關閉了。這就是他們願意做的事情的結束。

正如我所說,Web API OData 的管理還有很多問題(與 DateTime 無關,因此我不會在此列出)。 我一直是 OData 的堅定支持者,但 Web API OData 管理的明顯問題迫使我和我的團隊/公司放棄它。

幸運的是,普通的 Web API 可以設置為使用 OData 語法。設置控制器需要做更多的工作,但最終效果很好。它支持日期時間。(而且似乎擁有至少可以避免做出瘋狂錯誤決定的管理層。)

到目前為止,DateTime 不是OASIS OData V4 標準的一部分,Web API 不支持 DateTime 類型,但它支持 DateTimeOffset 類型。

但是,OData 團隊現在正在努力支持 DataTime 類型。我希望您可以在下一個 Web API 版本中使用 DateTime 類型。如果你等不及下一個版本,我根據 部落格寫了一個例子。希望它可以幫助你。謝謝。

模型

public class Customer
{
   private DateTimeWrapper dtw;

   public int Id { get; set; }

   public string Name { get; set; }

   public DateTime Birthday
   {
       get { return dtw; }
       set { dtw = value; }
   }

   [NotMapped]
   public DateTimeOffset BirthdayOffset
   {
       get { return dtw; }
       set { dtw = value; }
   }
}

public class DateTimeWrapper
{
   public static implicit operator DateTimeOffset(DateTimeWrapper p)
   {
       return DateTime.SpecifyKind(p._dt, DateTimeKind.Utc);
   }

   public static implicit operator DateTimeWrapper(DateTimeOffset dto)
   {
       return new DateTimeWrapper(dto.DateTime);
   }

   public static implicit operator DateTime(DateTimeWrapper dtr)
   {
       return dtr._dt;
   }

   public static implicit operator DateTimeWrapper(DateTime dt)
   {
       return new DateTimeWrapper(dt);
   }

   protected DateTimeWrapper(DateTime dt)
   {
       _dt = dt;
   }

   private readonly DateTime _dt;
}

數據庫上下文

public DbSet<Customer> Customers { get; set; }

模型

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

builder.EntitySet<Customer>("Customers");

var cu = builder.StructuralTypes.First(t => t.ClrType == typeof(Customer));
cu.AddProperty(typeof(Customer).GetProperty("BirthdayOffset"));
var customer = builder.EntityType<Customer>();

customer.Ignore(t => t.Birthday);
var model = builder.GetEdmModel();

config.MapODataServiceRoute("odata", "odata", model);

控制器

正常添加 OData 控制器。

測試

數據庫中的客戶數據

有效載荷

客戶有效載荷

最後,Web API OData v4 現在支持DateTime5.5 版中的類型。獲取最新的 nuget 包,不要忘記設置:

config.SetTimeZoneInfo(TimeZoneInfo.Utc);

否則 dateTime 屬性的時區將被視為本地時區。

更多資訊:ASP.NET Web API for OData V4 Docs DateTime support

引用自:https://stackoverflow.com/questions/25189557