EntityFramework Oracle 托管访问日期时间问题
EntityFramework with Oracle Managed Access DateTime issue
我有存储过程来根据输入参数执行搜索。
-- Search clients by specified input parameters.
create or replace procedure p_get_searchclients(i_iin in number default null,
i_full_name in varchar default null,
i_created_at_from in timestamp default null,
i_created_at_to in timestamp default null,
result_cursor out sys_refcursor) as
query_str varchar(200);
no_params_value exception;
begin
-- Check input parameters.
if i_iin is null and i_full_name is null and i_created_at_from is null and i_created_at_to is null
then
raise no_params_value;
end if;
-- Base query string.
query_str := 'select * from t_client where 1=1 ';
-- Add search by IIN column to the query.
if i_iin is not null
then
query_str := query_str || 'and iin like ''%' || i_iin || '%'' ';
end if;
-- Add search by FULL_NAME column to the query.
if i_full_name is not null
then
query_str := query_str || 'and lower(full_name) like ''%' || lower(i_full_name) || '%'' ';
end if;
-- Add search range by the CREATED_AT column to the query.
if i_created_at_from is not null and i_created_at_to is not null
then
query_str :=
query_str || 'and created_at >= ' || i_created_at_from || ' and created_at <= ' || i_created_at_to || ' ';
elsif i_created_at_from is not null and i_created_at_to is null
then
query_str := query_str || 'and created_at >= ' || i_created_at_from || ' ';
elsif i_created_at_from is null and i_created_at_to is not null
then
query_str := query_str || 'and created_at <= ' || i_created_at_to;
end if;
-- Execute statement.
open result_cursor for query_str;
exception
when no_params_value
then
raise_application_error(-20100, 'Необходимо указать как минимум один параметр для поиска.');
when others
then
rollback;
end p_get_searchclients;
在我的应用程序中,我使用了 EntityFramework 5.0 和 "EF Designer from Database" 方法。在 C# 中为我的存储过程自动生成的代码如下所示:
public virtual ObjectResult<P_GET_SEARCHCLIENTS_Result> P_GET_SEARCHCLIENTS(Nullable<decimal> i_IIN, string i_FULL_NAME, Nullable<System.DateTime> i_CREATED_AT_FROM, Nullable<System.DateTime> i_CREATED_AT_TO)
{
var i_IINParameter = i_IIN.HasValue ?
new ObjectParameter("I_IIN", i_IIN) :
new ObjectParameter("I_IIN", typeof(decimal));
var i_FULL_NAMEParameter = i_FULL_NAME != null ?
new ObjectParameter("I_FULL_NAME", i_FULL_NAME) :
new ObjectParameter("I_FULL_NAME", typeof(string));
var i_CREATED_AT_FROMParameter = i_CREATED_AT_FROM.HasValue ?
new ObjectParameter("I_CREATED_AT_FROM", i_CREATED_AT_FROM) :
new ObjectParameter("I_CREATED_AT_FROM", typeof(System.DateTime));
var i_CREATED_AT_TOParameter = i_CREATED_AT_TO.HasValue ?
new ObjectParameter("I_CREATED_AT_TO", i_CREATED_AT_TO) :
new ObjectParameter("I_CREATED_AT_TO", typeof(System.DateTime));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<P_GET_SEARCHCLIENTS_Result>("P_GET_SEARCHCLIENTS", i_IINParameter, i_FULL_NAMEParameter, i_CREATED_AT_FROMParameter, i_CREATED_AT_TOParameter);
}
如您所见,我在数据库中有 created_at
类型 timestamp
的列,它负责存储记录的创建日期。
因此,在我的应用程序中,我形成了 DateTime 参数(从 timestmap 到 DateTime 的转换),这些参数应该发送给 SP。
DateTime? i_createdAtFrom = null;
DateTime? i_createdAtTo = null;
if (long.TryParse(createdAtFrom, out long parsedFromDate))
i_createdAtFrom = DateTimeOffset.FromUnixTimeSeconds(parsedFromDate).LocalDateTime;
if (long.TryParse(createdAtTo, out long parsedToDate))
i_createdAtTo = DateTimeOffset.FromUnixTimeSeconds(parsedToDate).LocalDateTime;
该过程正常运行,没有任何错误,但是当我发送任何 createdAtFrom
或 createdAtTo
参数时,数据库抛出以下异常。
"ORA-00604: error occurred at recursive SQL level 1\nORA-01003: no statement parsed"
我认为这与将 C# DateTime
类型转换为 Oracle timestamp
的过程有某种联系,但我无法自行调试。
有什么想法吗?
我的配置:
Visual Studio 2017
EntityFramework 5.0
Oracle 客户端 11g 32 位
您应该使用准备好的语句和绑定参数。为了处理 NULL 值,您可以这样做:
-- Base query string.
query_str := 'select * from t_client where ';
-- Add search by IIN column to the query.
if i_iin is not null then
query_str := query_str || 'iin like :iin ';
else
query_str := query_str || ':iin IS NULL ';
end if;
-- Add search by FULL_NAME column to the query.
if i_full_name is not null then
query_str := query_str || 'and lower(full_name) like :i_full_name ';
else
query_str := query_str || 'and :i_full_name IS NULL ';
end if;
-- Add search range by the CREATED_AT column to the query.
if i_created_at_from is not null and i_created_at_to is not null then
query_str :=
query_str || 'and created_at >= :i_created_at_from and created_at <= :i_created_at_to ';
elsif i_created_at_from is not null and i_created_at_to is null then
query_str := query_str || 'and created_at >= :i_created_at_from AND :i_created_at_to IS NULL ';
elsif i_created_at_from is null and i_created_at_to is not null then
query_str := query_str || 'and created_at <= :i_created_at_to AND :i_created_at_from IS NULL ';
else
query_str := query_str || 'and :i_created_at_from IS NULL AND :i_created_at_to IS NULL ';
end if;
-- Execute statement.
open result_cursor
for query_str
USING '%'||iin||'%', '%'||LOWER(i_full_name)||'%', i_created_at_from, i_created_at_to;
我有存储过程来根据输入参数执行搜索。
-- Search clients by specified input parameters.
create or replace procedure p_get_searchclients(i_iin in number default null,
i_full_name in varchar default null,
i_created_at_from in timestamp default null,
i_created_at_to in timestamp default null,
result_cursor out sys_refcursor) as
query_str varchar(200);
no_params_value exception;
begin
-- Check input parameters.
if i_iin is null and i_full_name is null and i_created_at_from is null and i_created_at_to is null
then
raise no_params_value;
end if;
-- Base query string.
query_str := 'select * from t_client where 1=1 ';
-- Add search by IIN column to the query.
if i_iin is not null
then
query_str := query_str || 'and iin like ''%' || i_iin || '%'' ';
end if;
-- Add search by FULL_NAME column to the query.
if i_full_name is not null
then
query_str := query_str || 'and lower(full_name) like ''%' || lower(i_full_name) || '%'' ';
end if;
-- Add search range by the CREATED_AT column to the query.
if i_created_at_from is not null and i_created_at_to is not null
then
query_str :=
query_str || 'and created_at >= ' || i_created_at_from || ' and created_at <= ' || i_created_at_to || ' ';
elsif i_created_at_from is not null and i_created_at_to is null
then
query_str := query_str || 'and created_at >= ' || i_created_at_from || ' ';
elsif i_created_at_from is null and i_created_at_to is not null
then
query_str := query_str || 'and created_at <= ' || i_created_at_to;
end if;
-- Execute statement.
open result_cursor for query_str;
exception
when no_params_value
then
raise_application_error(-20100, 'Необходимо указать как минимум один параметр для поиска.');
when others
then
rollback;
end p_get_searchclients;
在我的应用程序中,我使用了 EntityFramework 5.0 和 "EF Designer from Database" 方法。在 C# 中为我的存储过程自动生成的代码如下所示:
public virtual ObjectResult<P_GET_SEARCHCLIENTS_Result> P_GET_SEARCHCLIENTS(Nullable<decimal> i_IIN, string i_FULL_NAME, Nullable<System.DateTime> i_CREATED_AT_FROM, Nullable<System.DateTime> i_CREATED_AT_TO)
{
var i_IINParameter = i_IIN.HasValue ?
new ObjectParameter("I_IIN", i_IIN) :
new ObjectParameter("I_IIN", typeof(decimal));
var i_FULL_NAMEParameter = i_FULL_NAME != null ?
new ObjectParameter("I_FULL_NAME", i_FULL_NAME) :
new ObjectParameter("I_FULL_NAME", typeof(string));
var i_CREATED_AT_FROMParameter = i_CREATED_AT_FROM.HasValue ?
new ObjectParameter("I_CREATED_AT_FROM", i_CREATED_AT_FROM) :
new ObjectParameter("I_CREATED_AT_FROM", typeof(System.DateTime));
var i_CREATED_AT_TOParameter = i_CREATED_AT_TO.HasValue ?
new ObjectParameter("I_CREATED_AT_TO", i_CREATED_AT_TO) :
new ObjectParameter("I_CREATED_AT_TO", typeof(System.DateTime));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<P_GET_SEARCHCLIENTS_Result>("P_GET_SEARCHCLIENTS", i_IINParameter, i_FULL_NAMEParameter, i_CREATED_AT_FROMParameter, i_CREATED_AT_TOParameter);
}
如您所见,我在数据库中有 created_at
类型 timestamp
的列,它负责存储记录的创建日期。
因此,在我的应用程序中,我形成了 DateTime 参数(从 timestmap 到 DateTime 的转换),这些参数应该发送给 SP。
DateTime? i_createdAtFrom = null;
DateTime? i_createdAtTo = null;
if (long.TryParse(createdAtFrom, out long parsedFromDate))
i_createdAtFrom = DateTimeOffset.FromUnixTimeSeconds(parsedFromDate).LocalDateTime;
if (long.TryParse(createdAtTo, out long parsedToDate))
i_createdAtTo = DateTimeOffset.FromUnixTimeSeconds(parsedToDate).LocalDateTime;
该过程正常运行,没有任何错误,但是当我发送任何 createdAtFrom
或 createdAtTo
参数时,数据库抛出以下异常。
"ORA-00604: error occurred at recursive SQL level 1\nORA-01003: no statement parsed"
我认为这与将 C# DateTime
类型转换为 Oracle timestamp
的过程有某种联系,但我无法自行调试。
有什么想法吗?
我的配置:
Visual Studio 2017
EntityFramework 5.0
Oracle 客户端 11g 32 位
您应该使用准备好的语句和绑定参数。为了处理 NULL 值,您可以这样做:
-- Base query string.
query_str := 'select * from t_client where ';
-- Add search by IIN column to the query.
if i_iin is not null then
query_str := query_str || 'iin like :iin ';
else
query_str := query_str || ':iin IS NULL ';
end if;
-- Add search by FULL_NAME column to the query.
if i_full_name is not null then
query_str := query_str || 'and lower(full_name) like :i_full_name ';
else
query_str := query_str || 'and :i_full_name IS NULL ';
end if;
-- Add search range by the CREATED_AT column to the query.
if i_created_at_from is not null and i_created_at_to is not null then
query_str :=
query_str || 'and created_at >= :i_created_at_from and created_at <= :i_created_at_to ';
elsif i_created_at_from is not null and i_created_at_to is null then
query_str := query_str || 'and created_at >= :i_created_at_from AND :i_created_at_to IS NULL ';
elsif i_created_at_from is null and i_created_at_to is not null then
query_str := query_str || 'and created_at <= :i_created_at_to AND :i_created_at_from IS NULL ';
else
query_str := query_str || 'and :i_created_at_from IS NULL AND :i_created_at_to IS NULL ';
end if;
-- Execute statement.
open result_cursor
for query_str
USING '%'||iin||'%', '%'||LOWER(i_full_name)||'%', i_created_at_from, i_created_at_to;