EF Core查询到Oracle,抛出非unicode列“ORA-12704:字符集不匹配”

xdnvmnnf  于 2023-08-03  发布在  Oracle
关注(0)|答案(1)|浏览(108)

我在DataContext中有这段代码

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    #region Province

    var provinceEntity = modelBuilder.Entity<Province>();
    provinceEntity.ToTable("GTPROVINCES");

    #region properties

    provinceEntity.Property(table => table.ProvinceId).HasColumnName("PROVINCEID");
    provinceEntity.Property(table => table.Name).HasColumnName("NAME").IsUnicode(false);

    #endregion properties

    #region keys

    provinceEntity.HasKey(e => new { e.ProvinceId });
    #endregion keys

    #endregion Province
}

字符串
我有一个ApiController,代码如下:

[HttpGet]
public async Task<IActionResult> Index()
{
    string test1 = "test1";
    string test2 = "test2";

    var lista = unitOfWork.ProvinceRepository.Fetch().Select(x => new
        {
            name = x.Name == test1 ? test1 : test2
        });
    System.Diagnostics.Debug.WriteLine(lista.ToQueryString());
    lista.ToList();

    return new EmptyResult();
}


当运行ToList()时,我得到这个错误:
ORA-12704:字符集不匹配
问题是向数据库发起的查询是

DECLARE 
l_sql     varchar2(32767);
l_cur     pls_integer;
l_execute pls_integer;

BEGIN
l_cur := dbms_sql.open_cursor;
l_sql := 'SELECT CASE
    WHEN "g"."NAME" = :test1_0 THEN :test1_0
    ELSE :test2_1
END "name"
FROM "GTPROVINCES" "g"';
dbms_sql.parse(l_cur, l_sql, dbms_sql.native);
dbms_sql.bind_variable(l_cur, ':test1_0', 'test1');
dbms_sql.bind_variable(l_cur, ':test2_1', N'test2');
l_execute:= dbms_sql.execute(l_cur);
dbms_sql.return_result(l_cur);
END;


它混合了ansi字符中的test1和unicode字符中的test 2。
有人能帮帮我吗?
我希望所有文字都是ansi字符。

pgx2nnw8

pgx2nnw81#

您可能需要删除三元操作:

name = x.Name == test1 ? test1 : test2)

字符串
...而是返回一个标志,以确定名称是否与您的条件匹配,然后才最终返回所需的值。EF将遵守Unicode与属性的非Unicode字符串比较,但是,当您有效地将if/else引入子句时,“test 2”Unicode字符串将被解析为Unicode字符串进入查询表达式,然后该表达式将尝试返回非Unicode值或导致错误的Unicode值。
例如,这应该工作:

var lista = unitOfWork.ProvinceRepository.Fetch().Select(x => new
    {
        isTest1 = x.Name == test1
    }).AsEnumerable()
    .Select(x => new 
    {
        name = isTest1 ? test1 : test2
    }).ToList();


……作为一个例子。这就形成了一个双投影,第一个Select被转换为SQL,而第二个AsEnumerable之后的Select在内存中执行。如果您有Where子句,请确保将它们添加到AsEnumerable之前。另外,第一个Select需要包含您希望包含在最终投影中的表行中的任何值。如果您需要无法转换为SQL的值,则此方法非常有用。

相关问题