是否可以在具有 EntityFramework 的 DateTimeOffset 列上使用 Computed 的 StoreGeneratedPattern?

Should it be possible to use a StoreGeneratedPattern of Computed on a DateTimeOffset column with EntityFramework?

如果我在 Oracle 数据库中有一个 table,其中有一个名为 LastModified 的 TIMESTAMP(6) WITH TIMEZONE 列,我希望使用 EntityFramework 对其建模;是否可以将该列标记为 DatabaseGeneratedOption.Computed?

我有前面提到的 table 并且已经成功地使用 EF6 和 Oracle.ManagedDataAccess.Client 创建了一个模型 first/db 第一个 edmx 模型。根据文档,TIMESTAMP(6) WITH TIMEZONE 列被映射为 DateTimeOffset,我手动将 LastModified 标记为 Computed。

这适用于 SELECT 语句,但是当我尝试进行更新时,出现以下错误:

A store-generated value of type 'System.DateTime' could not be converted to a value of type 'System.DateTimeOffset' required for member 'LastModified' of type ....

深入研究异常和堆栈跟踪产生:

Invalid cast from 'System.DateTime' to 'System.DateTimeOffset'.

at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) at System.DateTime.System.IConvertible.ToType(Type type, IFormatProvider provider) at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Data.Entity.Core.Mapping.Update.Internal.PropagatorResult.AlignReturnValue(Object value, EdmMember member)

我花了一些时间查看 EntityFramework 源代码,似乎处理返回数据库生成值的代码没有使用与 SELECT 或模型相同的映射逻辑创作逻辑。

这导致 TIMESTAMP(6) WITH TIMEZONE 在作为数据库生成值从数据库检索时被映射到 DateTime,然后在尝试将其转换为 DateTimeOffset 时失败。

这是known/expected行为吗?我错过了某个地方的设置吗?或者在使用 StoreGeneratedPatten 时是否只有有限的类型子集可以使用 "None"?

调试 EntityFramework 并最终完全绕过它后,我发现问题出在提供程序 (Oracle.ManagedDataAccess.Client) 上。在具有 TIMESTAMP(6) WITH TIMEZONE 计算列的 table 上通过 EntityFramework 的更新生成如下所示的 sql:

DECLARE "COLUMNC_FOROUTPUT" TIMESTAMP WITH TIME ZONE;

BEGIN
  UPDATE "SCHEMA"."TABLEA"
  SET "COLUMNB" = :p0
  WHERE ("COLUMNA" = :p1)
  RETURNING "COLUMNC" INTO "COLUMNC_FOROUTPUT";

  OPEN :p2 FOR 
  SELECT "COLUMNC_FOROUTPUT" AS "COLUMNC_FOROUTPUT" FROM dual;
END;

其中 :p2 是一个 REF CURSOR。如果将上述 sql 和适当的参数直接提供给 ODP.Net,则使用 ExecuteReader()reader.GetFieldValue<object>(0) 会产生类型为 DateTime 的对象,这与TIMESTAMP(6) WITH TIMEZONE 应该映射到 (DateTimeOffset)。

我想还需要另一个关于 ODP.Net、REF CURSORS 和 TIMESTAMP WITH TIME ZONE 映射的问题,因为我原来问题的答案似乎是 "Yes but not if you're using the latest version of Oracle.ManagedDataAccess.Client as a provider"。

更新

实际上,如果涉及引用游标,则没有任何区别,问题出在 Oracle.ManagedDataAccess.Client.OracleTypeMapper class 中,它将带 TZ 的时间戳映射到 DateTime 而不是 DateTimeOffset。这将影响对 OracleDataReader 上的 GetFieldValue 的任何调用。

我已经在 ODP.Net 论坛上询问了 question,看看是否有人可以确认这是否是正确的行为。