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

时间:2016-06-09 14:41:49

标签: c# entity-framework odp.net

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

我有上述表并已成功使用EF6和Oracle.ManagedDataAccess.Client创建模型first / db first edmx模型。根据文档,TIMESTAMP(6) WITH TIMEZONE列被映射为DateTimeOffset,我手动将LastModified标记为Computed。

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

  

商店生成的“System.DateTime”类型的值不可能   转换为需要的类型为'System.DateTimeOffset'的值   成员'LastModified'的类型....

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

  

从'System.DateTime'到'System.DateTimeOffset'的转换无效。

     

在System.Convert.DefaultToType(IConvertible值,Type targetType,   IFormatProvider提供商)   System.DateTime.System.IConvertible.ToType(Type type,IFormatProvider   System.Convert.ChangeType(Object value,Type。)   conversionType,IFormatProvider provider)at   System.Data.Entity.Core.Mapping.Update.Internal.PropagatorResult.AlignReturnValue(对象   价值,Edm会员)

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

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

这是已知/预期的行为吗?我错过了某个地方的设置吗?或者只有一个有限的类型子集可以在使用不是“无”的StoreGeneratedPatten时使用?

1 个答案:

答案 0 :(得分:0)

调试了EntityFramework并最终完全绕过它后,我发现问题在于提供程序(Oracle.ManagedDataAccess.Client)。在具有TIMESTAMP(6) WITH TIMEZONE计算列的表上通过EntityFramework进行UPDATE生成如下所示的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映射的问题,因为我原来问题的答案似乎是“是的,但如果您使用的是最新版本的Oracle.ManagedDataAccess则不行。”客户作为提供者“。

更新

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

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