Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架代码第一个字符串与Oracle Db的比较_C#_Oracle_Linq_Ef Code First_String Comparison - Fatal编程技术网

C# 实体框架代码第一个字符串与Oracle Db的比较

C# 实体框架代码第一个字符串与Oracle Db的比较,c#,oracle,linq,ef-code-first,string-comparison,C#,Oracle,Linq,Ef Code First,String Comparison,我在使用代码优先与Oracle db进行不区分大小写的字符串比较时遇到问题。代码看起来像这样 String filter = "Ali"; var employee = dbContext.Employees.Where(x => x.Name.Contains(filter)).FirstOrDefault(); 上述代码区分大小写。因此,我将名称和过滤器都转换为大写 String filter = "Ali"; filter = filter.ToUpper(); var emplo

我在使用代码优先与Oracle db进行不区分大小写的字符串比较时遇到问题。代码看起来像这样

String filter = "Ali";
var employee = dbContext.Employees.Where(x => x.Name.Contains(filter)).FirstOrDefault();
上述代码区分大小写。因此,我将名称和过滤器都转换为大写

String filter = "Ali";
filter = filter.ToUpper();
var employee = dbContext.Employees.Where(x => x.Name.ToUpper().Contains(filter)).FirstOrDefault();
起初一切似乎都正常,但后来我意识到,当员工的姓名或过滤器包含字符“I”时,一切都不正常。问题是“我”这封信是如何用土耳其语写的

在大多数语言中,“i”代表小写,而“i”代表字符的大写版本。然而,在土耳其语中,“i”的大写字母是“İ”,而“i”的小写字母是“ı”。这是一个问题,因为Oracle将db中的字母“i”大写为“i”

我们无法访问db的字符编码设置,因为其效果无法轻易预见

我想到的是这个,非常难看

String filterInvariant = filter.ToUpper(CultureInfo.InvariantCulture);
String filterTurkish = filter.ToUpper(CultureInfo.CreateSpecificCulture("tr-TR"));
var employee = dbContext.Employees.Where(x => x.Name.ToUpper().Contains(filterInvariant) || x.Name.ToUpper().Contains(filterTurkish)).FirstOrDefault();
它似乎解决了一些问题,但感觉像是一个强力解决方案,而不是一个可靠的解决方案。在对Oracle数据库使用Code First C时,此解决方案的最佳实践或替代方案是什么


提前感谢

对于不同的提供程序,String.Contains的实现是不同的,例如Linq2Sql总是不区分大小写。搜索是否区分大小写取决于服务器设置。例如,默认情况下SQL Server将SQL拉丁1\u通用CP1\u CI\u作为排序规则,并且不区分大小写。对于Oracle,可以在会话级别更改此行为:在会话开始时使用context.Database.ExecuteSqlCommand方法发出原始SQL查询

FILES.Where(t => t.FILE_NAME.ToUpper() == "FILE.TXT") // Get rows from file-table
使用我拥有的Oracle提供程序转换为以下Oracle SQL:

SELECT t0.BINARY_FILE, t0.FILE_NAME, t0.FILE_SIZE, t0.INFO, t0.UPLOAD_DATE
FROM FILES t0
WHERE (UPPER(t0.FILE_NAME) = :p0)
-- p0 = [FILE.TXT]
包含的内容首先变为:

SELECT * FROM (SELECT t0.BINARY_FILE, t0.FILE_NAME, t0.FILE_SIZE, t0.INFO, t0.UPLOAD_DATE
            FROM FILES t0
            WHERE ((UPPER(t0.FILE_NAME) LIKE '%' || :p0 || '%') 
                OR (UPPER(t0.FILE_NAME) LIKE '%' || :p1 || '%'))) 
WHERE ROWNUM<=1
-- p0 = [FILE.TXT]
-- p1 = [FİLE.TXT]
因此,这取决于数据库的区域性设置,即在不了解它们的情况下,我认为与解决方案重叠是解决此问题的最佳方法。为什么不能只检查数据库区域性设置?

使用上面的所有函数。只需让Oracle执行语言感知的不区分大小写匹配。这是通过将C中的DB连接设置为具有适当的语言参数来实现的。此设置仅适用于数据库会话,而不是整个数据库的全局更改。我不是C向导,所以您必须在db连接/池代码中找出在何处进行这些会话设置

ALTER SESSION SET nls_language=TURKISH;
ALTER SESSION SET nls_comp=LINGUISTIC;
ALTER SESSION SET nls_sort=BINARY_CI;
如果C很难找到更改的位置,您可以将其设置为下面的用户/模式登录触发器,它会在db连接时自动为您设置这些触发器,并使用实际的db用户名替换SOMEUSER。这只会影响任何新的db会话,因此如果连接池中有连接,则需要循环db连接池以刷新连接

CREATE OR REPLACE TRIGGER SOMEUSER.SET_NLS_CASE_INSENSITIVE_TRG AFTER
                   LOGON ON SOMEUSER.SCHEMA
  BEGIN
    EXECUTE IMMEDIATE 'ALTER SESSION SET nls_language=TURKISH';
    EXECUTE IMMEDIATE 'ALTER SESSION SET nls_comp=LINGUISTIC';
    EXECUTE IMMEDIATE 'ALTER SESSION SET nls_sort=BINARY_CI';
  END;
/
下面是我在Oracle DB中做的一个小测试:

CREATE TABLE mypeople (name VARCHAR2(10 CHAR));

INSERT INTO mypeople VALUES ('Alİ Hassan');
INSERT INTO mypeople VALUES ('AlI Hassan');
INSERT INTO mypeople VALUES ('Ali Hassan');
INSERT INTO mypeople VALUES ('Alı Hassan');

SELECT name FROM mypeople WHERE name LIKE 'Ali%';

NAME
----------
Ali Hassan

ALTER SESSION SET nls_language=TURKISH;
ALTER SESSION SET nls_comp=LINGUISTIC;
ALTER SESSION SET nls_sort=BINARY_CI;

SELECT name FROM mypeople WHERE name LIKE 'Ali%';

NAME
----------
Alİ Hassan
AlI Hassan
Ali Hassan

谢谢你非常详细的回复Joshua,这既有帮助又信息丰富。Yw,很高兴能提供帮助。还有,我要你的赏金。