1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/riwfnsse-MYear.ODA

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

MYear.ODA

Введение

C# .Net Database ORM для Oracle DB2 MySql SqlServer SQLite MariaDB; чистая c# разработка, поддержка .NetCore 2.0, .Net standard

MYear.ODA — это компонент ORM для доступа к базе данных, который может работать с широко используемыми базами данных DB2, Oracle, SqlServer, MySql (MariaDB), SQLite; также можно легко использовать его для менее распространённых баз данных Informix, Sybase, Access; на данный момент MYear.ODA является наиболее полным компонентом C# ORM, поддерживающим синтаксис SQL; также он имеет хороший потенциал для расширения для работы с секционированными таблицами или распределёнными базами данных.

Разбиение на страницы, динамическое добавление условий, подзапросы, бесконечные соединения, объединение, группировка по, наличие, вложенные запросы, существование, вставка подзапросов, импорт и высокоскоростная загрузка — всё это характерные особенности ODA.

Он позволяет пользователям внедрять фрагменты кода SQL, а также писать собственный код SQL, и поддерживает процедуры (или пакеты Oracle); поскольку многие разработчики предпочитают простоту лямбда-выражений, ODA также расширил эту функцию.

ODA может повысить производительность разработчиков, стандартизировать способ написания кода и уменьшить проблемы с доступом к базе данных в больших командах разработчиков с разным уровнем навыков.

Производительность, функциональность, стабильность работы и параллельная производительность ODA являются очень сильными, не уступая Dapper, EF, SqlSugar.

Примечание: уже есть реальные проекты, которые свободно переключаются между тремя базами данных Oracle, Mysql и SqlServer.

Конечно, при создании таблиц следует избегать ключевых слов различных баз данных и обращать внимание на чувствительность к регистру записей данных в разных базах данных.

Синтаксис MYear.ODA

ODA использует синтаксис цепочечного программирования, напрямую сопоставляя SQL-запросы, поэтому синтаксис ODA похож на SQL, только Select, Insert, Update и Delete помещаются после. Поскольку ODA напрямую отображает SQL-запросы, он не выполняет никаких преобразований, как EF, что приводит к сложным и неэффективным SQL-запросам, которые трудно оптимизировать. При использовании ODA, если вы запутались, вы можете использовать SQL-запрос для вывода соответствующего синтаксиса ODA; обучение стоит очень дёшево, и его легко освоить, и вам не нужно тратить много времени на изучение, как с EF. Чтобы обеспечить совместимость с различными базами данных, SQL-запросы, генерируемые ODA, являются стандартными и универсальными; некоторые часто используемые, но несовместимые части реализованы внутри ODA (например, рекурсивные древовидные запросы и разбиение на страницы).

Методы MYear.ODA Select, Insert, Update, Delete и Procedure используются в качестве окончательных методов выполнения; когда эти методы вызываются, ODA отправляет сгенерированный SQL-запрос в базу данных для выполнения.

Тестирование производительности

В информационных системах управления бизнес-функции не требуют максимальной производительности, достаточно удовлетворить общие требования взаимодействия человека с компьютером; но в базовых фреймворках или глобальных программах (таких как компоненты ORM и контейнеры AOP) мы стремимся к максимальной производительности при достижении определённого масштаба параллелизма. Производительность ORM влияет на общую производительность системы, и её использование, удобство обслуживания и влияние на разработчиков имеют всестороннее влияние на производительность всей системы. Из-за инвазивности ORM плохой ORM может привести разработчиков в заблуждение и привести их к бездонной яме; EF — хороший пример обратного обучения. Данные и производительность отображения EF не очень хороши, скорость генерации SQL-запросов низкая, но самая ненадёжная часть — это сгенерированные SQL-запросы. Сгенерированные EF SQL-запросы содержат множество преобразований и очень сложны, часто не могут использовать индексы и не поддаются оптимизации, что делает выполнение этих запросов в базе данных чрезвычайно медленным. Кроме того, синтаксис EF и Linq требует больших усилий для изучения, а эффективность разработки низкая, код трудно поддерживать, и в целом это кошмар. Хотя производительность ORM сама по себе не так важна (хотя производительность ODA очень сильна), ключевым моментом является то, что ORM не должен вводить разработчиков в заблуждение, а затем обеспечивать стандартизированный доступ к коду программы базы данных, повышать удобство сопровождения программы и одновременно повышать эффективность разработки, поддерживать последующие расширения приложений (такие как секционирование, секционирование таблиц, совместное использование нескольких баз данных) и ORM должны быть универсальными для баз данных, одновременно ограничивая разработчиков от использования специфичных для базы данных функций. Это цель ORM. Чтение одной записи данных Dapper немного опережает ODA, но время прогрева (первая запись) довольно длительное. ODA явно превосходит EF и SqlSugar; особенно EF значительно уступает остальным. SQL генерация производительности. Dapper не сравнивается, поскольку у него нет этой функции; скорость генерации операторов EF просто невыносима. ODA в несколько раз лучше, чем Sqlsugar. Запрос на постраничный поиск. Dapper, без учёта функций, не сравнивается; EF, ODA, Sqlsugar — разница в производительности незначительна. Использование ODA

Подключение к базе данных

// Глобальная настройка
ODAContext.SetODAConfig(DbAType.MsSQL, "server=localhost;database=master;uid=sa;pwd=sa;");

// Настройка для отдельного контекста
var ctx = new ODAContext(DbAType.MsSQL,"server=localhost;database=master;uid=sa;pwd=sa;"); 

Запрос

Простой запрос

В ODA можно легко использовать ключевые слова SQL.

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
object data = U.Where(U.USER_NAME == "Lambda")
                  .And(U.IS_LOCKED == "N")
                  .And(U.STATUS == "O") 
                 .Select(U.USER_ACCOUNT, U.USER_PASSWORD.As("PWD"), U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR,U.ADDRESS,U.CREATED_DATE); 
SELECT T0.USER_ACCOUNT, T0.USER_PASSWORD AS PWD, T0.USER_NAME, T0.PHONE_NO, T0.EMAIL_ADDR
    , T0.ADDRESS, T0.CREATED_DATE
FROM SYS_USER T0
WHERE T0.USER_NAME = 'Lambda'
    AND T0.IS_LOCKED = 'N'
    AND T0.STATUS = 'O'

Запрос по умолчанию для сущности

Для упрощения однотабличного запроса до сущности ODA предоставляет метод SelectM, который возвращает данные по умолчанию для сущности. Этот метод является повторной инкапсуляцией универсального метода Select<> и работает аналогично ему.

ODAContext ctx = BizContext.GetContext();
 var U = ctx.SYS_USER();
List<SYS_USER> data = U.Where(U.CREATED_BY == "Insert", U.IS_LOCKED == "N", U.STATUS == "O")
   .SelectM(U.USER_ACCOUNT, U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR, U.CREATED_DATE);
SELECT T0.USER_ACCOUNT, T0.USER_NAME, T0.PHONE_NO, T0.EMAIL_ADDR, T0.CREATED_DATE
FROM SYS_USER T0
WHERE T0.CREATED_BY = 'Insert'
    AND T0.IS_LOCKED = 'N'
    AND T0.STATUS = 'O'      

Запрос с возвратом указанного типа сущности

Возвращаемый тип сущности может быть любым пользовательским типом, не обязательно совпадающим с сущностью базы данных. Универсальный метод Select<> не предъявляет особых требований к типу передаваемой сущности, и его свойства будут присвоены соответствующим образом, если они совпадают с именами полей запроса. Количество свойств в сущности не обязательно должно совпадать с количеством полей в запросе.

ODAContext ctx = BizContext.GetContext();
 var U = ctx.SYS_USER();
List<SYS_USER> data = U.Where(U.CREATED_BY.Like("Import%"))
    .And(U.IS_LOCKED == "N")
    .And(U.STATUS == "O")
    .And(U.EMAIL_ADDR.IsNotNull)
    .Select<SYS_USER>(U.USER_ACCOUNT, U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR);
SELECT T0.USER_ACCOUNT, T0.USER_NAME, T0.PHONE_NO, T0.EMAIL_ADDR
FROM SYS_USER T0
WHERE T0.CREATED_BY LIKE 'Import%'
    AND T0.IS_LOCKED = 'N'
    AND T0.STATUS = 'O'
    AND T0.EMAIL_ADDR IS NOT NULL

Запрос с разбиением на страницы

ODAContext ctx = BizContext.GetContext();
int total = 0; 
var U = ctx.SYS_USER();
var data = U.Where(U.CREATED_BY.ContainLeft("Import"), U.IS_LOCKED == "N")
.SelectM(0,20,out total, U.CREATED_BY,U.CREATED_DATE, U.USER_ACCOUNT, U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR); 
    
SELECT T0.CREATED_BY, T0.CREATED_DATE, T0.USER_ACCOUNT, T0.USER_NAME, T0.PHONE_NO
    , T0.EMAIL_ADDR
FROM SYS_USER T0
WHERE T0.CREATED_BY LIKE 'Import%'
    AND T0.IS_LOCKED = 'N';

SELECT COUNT(*) AS TOTAL_RECORD
FROM SYS_USER T0
WHERE T0.CREATED_BY LIKE 'Import%'
    AND T0.IS_LOCKED = 'N'

Запрос первой строки

Часто при запросе к базе данных требуется только первая строка данных. Для упрощения работы приложения ODA предлагает метод для запроса первой строки данных и возврата динамического типа данных. Результат будет динамическим типом, значения которого можно получить по именам полей запроса.

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var data = U.Where(U.CREATED_BY == "InsertModel", U.IS_LOCKED == "N", U.USER_NAME.IsNotNull)
.SelectDynamicFirst(U.USER_ACCOUNT, U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR);

            string UserName = data.USER_NAME; ///属性 USER_NAME 与 USER_NAME 的ColumnName一致,如果没有数据则返回null
SELECT T0.USER_ACCOUNT, T0.USER_NAME, T0.PHONE_NO, T0.EMAIL_ADDR
FROM SYS_USER T0
WHERE T0.CREATED_BY = 'InsertModel'
    AND T0.IS_LOCKED = 'N'
    AND T0.USER_NAME IS NOT NULL;

SELECT COUNT(*) AS TOTAL_RECORD
FROM SYS_USER T0
WHERE T0.CREATED_BY = 'InsertModel'
    AND T0.IS_LOCKED = 'N'
    AND T0.USER_NAME IS NOT NULL 

Возврат динамической модели данных

Иногда создание отдельного класса сущности для небольшого запроса может быть слишком трудоёмким. ODA сама предоставляет динамический тип возвращаемого значения, что очень удобно для программ, обрабатывающих небольшое количество данных.

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var data = U.Where(U.CREATED_BY == "Lambda", U.IS_LOCKED == "N", U.EMAIL_ADDR.IsNotNull)
.SelectDynamic(U.USER_ACCOUNT, U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR);

string UserName = "";
if (data.Count > 0)
    UserName =  data[0].USER_NAME; ///与 USER_NAME  的 ColumnName一致.
SELECT T0.USER_ACCOUNT, T0.USER_NAME, T0.PHONE_NO, T0.EMAIL_ADDR
FROM SYS_USER T0
WHERE T0.CREATED_BY = 'Lambda'
    AND T0.IS_LOCKED = 'N'
    AND T0.EMAIL_ADDR IS NOT NULL **Отбор неповторяющихся значений (Distinct)**

```C#
ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var data = U.Where(U.IS_LOCKED == "N", U.EMAIL_ADDR.IsNotNull)
.Distinct.Select(U.USER_ACCOUNT, U.USER_NAME, U.PHONE_NO, U.EMAIL_ADDR);
SELECT DISTINCT T0.USER_ACCOUNT, T0.USER_NAME, T0.PHONE_NO, T0.EMAIL_ADDR
FROM SYS_USER T0
WHERE T0.IS_LOCKED = 'N'
    AND T0.EMAIL_ADDR IS NOT NULL

Соединение запросов

ODA поддерживает InnerJoin, LeftJoin, RightJoin, и можно бесконечно Join. Условия On также очень гибкие, ODA в основном поддерживает все условия, которые поддерживаются SQL-операторами.

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var R = ctx.SYS_ROLE();
var UR = ctx.SYS_USER_ROLE();

///LeftJoin\InnerJoin\RightJoin 可以无限连接,但实际上每种数据库都有对SQL语句长度作限制。
var data = U.InnerJoin(UR, U.USER_ACCOUNT == UR.USER_ACCUNT, UR.STATUS == "O")
    .LeftJoin(R, UR.ROLE_CODE == R.ROLE_CODE, R.STATUS == "O")
    .Where(U.STATUS == "O", R.ROLE_CODE == "Administrator")
     .Select<UserDefineModel>(U.USER_ACCOUNT.As("UserAccount"), U.USER_NAME.As("UserName"), R.ROLE_CODE.As("Role"), R.ROLE_NAME.As("RoleName"));
SELECT T0.USER_ACCOUNT AS UserAccount, T0.USER_NAME AS UserName, T1.ROLE_CODE AS Role, T1.ROLE_NAME AS RoleName
FROM SYS_USER T0
    INNER JOIN SYS_USER_ROLE T2
    ON T0.USER_ACCOUNT = T2.USER_ACCOUNT
        AND T2.STATUS = 'O'
    LEFT JOIN SYS_ROLE T1
    ON T2.ROLE_CODE = T1.ROLE_CODE
        AND T1.STATUS = 'O'
WHERE T0.STATUS = 'O'
    AND T1.ROLE_CODE = 'Administrator'

Простое внутреннее соединение

Внутреннее соединение имеет множество людей, которые используют только join, но для формы SELECT t1.* FROM TABLE1 T1, TABLE2 T2, TABLE3 T3, TABLE4 этот способ написания может быть незнакомым. Однако я считаю, что этот способ соединения проще и легче для чтения.

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var R = ctx.SYS_ROLE();
var UR = ctx.SYS_USER_ROLE();
var data =  U.ListCmd(UR,R)
    .Where(U.USER_ACCOUNT == UR.USER_ACCOUNT, 
     UR.STATUS == "O",
     UR.ROLE_CODE == R.ROLE_CODE,
     R.STATUS == "O",
     U.STATUS == "O",
     R.ROLE_CODE == "Administrator")
     .Select< UserDefineModel>(U.USER_ACCOUNT.As("UserAccount"), U.USER_NAME.As("UserName"),U.EMAIL_ADDR.As("Email"), R.ROLE_CODE.As("Role"), R.ROLE_NAME.As("RoleName"));

-------------

            int total = 0;
            var data = new ODAContext().From<SysUser, SysUserRole, SysRole, SysRoleAuthorization>()
                 .Where((u, ur, r, ra) => u.USER_ACCOUNT == ur.USER_ACCOUNT & ur.STATUS == "O"
                 & ur.ROLE_CODE == r.ROLE_CODE & r.STATUS == "O"
                 & r.ROLE_CODE == ra.ROLE_CODE & ra.IS_FORBIDDEN == "O" & ra.STATUS == "O"
                 & u.STATUS == "O" & (r.ROLE_CODE == "Administrator" | r.ROLE_CODE == "Admin") & u.IS_LOCKED == "N")
                 .Groupby((u, ur, r, ra) => new[] { r.ROLE_CODE, u.USER_ACCOUNT })
                 .Having((u, ur, r, ra) => ra.RESOURCE_ID.Count > 10)
                 .OrderbyAsc((u, ur, r, ra) => new[] { ra.RESOURCE_ID.Count })
                 .Select(0, 20, out total, (u, ur, r, ra) => new[] { r.ROLE_CODE, u.USER_ACCOUNT, ra.RESOURCE_ID.Count.As("ResourceCount") });
            return data;
SELECT T0.USER_ACCOUNT AS UserAccount, T0.USER_NAME AS UserName, T0.EMAIL_ADDR AS Email, T1.ROLE_CODE AS Role, T1.ROLE_NAME AS RoleName
FROM SYS_USER T0, SYS_USER_ROLE T2, SYS_ROLE T1
WHERE T0.USER_ACCOUNT = T2.USER_ACCOUNT
    AND T2.STATUS = 'O'
    AND T2.ROLE_CODE = T1.ROLE_CODE
    AND T1.STATUS = 'O'
    AND T0.STATUS = 'O'
    AND T1.ROLE_CODE = 'Administrator'

---------------
SELECT T2.ROLE_CODE,T0.USER_ACCOUNT,COUNT(T3.RESOURCE_ID) AS ResourceCount 
FROM SYS_USER T0,SYS_USER_ROLE T1,SYS_ROLE T2,SYS_ROLE_AUTHORIZATION T3 
WHERE (T0.USER_ACCOUNT = T1.USER_ACCOUNT 
  AND T1.STATUS = 'O' 
  AND T1.ROLE_CODE = T2.ROLE_CODE 
  AND T2.STATUS = 'O' 
  AND T2.ROLE_KEY = T3.ROLE_CODE 
  AND T3.IS_FORBIDDEN = 'O' 
  AND T3.STATUS = 'O' 
  AND T0.STATUS = 'O' 
  AND (T2.ROLE_CODE = 'Administrator' OR T2.ROLE_CODE = 'Admin') 
  AND T0.IS_LOCKED = 'N') 
GROUP BY T2.ROLE_CODE,T0.USER_ACCOUNT 
HAVING COUNT(T3.RESOURCE_ID) > 10 
ORDER BY COUNT(T3.RESOURCE_ID) ASC

Вложенные подзапросы

Для вложенных подзапросов необходимо преобразовать один запрос в представление (ToView метод), после преобразования его можно использовать как обычный Cmd. В представлении ViewColumns — это набор полей представления. Текст запроса:

BizContext.GetContext(); var U = ctx.SYS_USER(); var R = ctx.SYS_ROLE(); var UR = ctx.SYS_USER_ROLE();

var UA = ctx.GetCmd(); var RA = ctx.SYS_ROLE_AUTHORIZATION();

var Admin = U.InnerJoin(UR, U.USER_ACCOUNT == UR.USER_ACCOUNT, UR.STATUS == "O") .InnerJoin(R, UR.ROLE_CODE == R.ROLE_CODE, R.STATUS == "O") .Where(U.STATUS == "O") .ToView(U.USER_ACCOUNT.As("SYS_USER"), U.USER_NAME, R.ROLE_CODE.As("SYS_ROLE"), R.ROLE_NAME); ////子查询

       var data =  Admin.InnerJoin(UA, UA.USER_ACCOUNT == Admin.ViewColumns[1],UA.IS_FORBIDDEN == "N")
.InnerJoin(RA,RA.ROLE_CODE == Admin.ViewColumns[2],RA.IS_FORBIDDEN =="N") 
.Where(Admin.ViewColumns[0] == "MYEAR_Insert",
Admin.ViewColumns[2] == "Administrator")
.Select(); 
**Перевод текста на русский язык:**

BizContext.GetContext();
var У = ctx.SYS_USER();
var Р = ctx.SYS_ROLE();
var УР = ctx.SYS_USER_ROLE();   

var ЮА = ctx.GetCmd<SysUserAuthorization>();
var РА = ctx.SYS_ROLE_AUTHORIZATION();

var Админ = У.InnerJoin(УР, У.USER_ACCOUNT == УР.USER_ACCOUNT, УР.STATUS == «О»)
    .InnerJoin(Р, УР.ROLE_CODE == Р.ROLE_CODE, Р.STATUS == «О»)
    .Где(У.STATUS == «О»)
    .ТоВиев(У.USER_ACCOUNT.Ас("SYS_USER"), У.USER_NAME, Р.ROLE_CODE.Ас("SYS_ROLE"), Р.ROLE_NAME); ////подзапрос

       var данные = Админ.InnerJoin(ЮА, ЮА.USER_ACCOUNT == Админ.ВиевКолоунс[1], ЮА.IS_FORBIDDEN == «Н»)
    .InnerJoin(РА, РА.ROLE_CODE == Админ.ВиевКолоунс[2], РА.IS_FORBIDDEN == «Н») 
    .Где(Админ.ВиевКолоунс[0] == «MYEAR_Insert»,
    Админ.ВиевКолоунс[2] == «Администратор»)
    .Выбрать(); 

В запросе используется язык программирования C#, а также язык запросов SQL. **Метод эквивалентен.**

Условия для фильтрации данных можно динамически добавлять в зависимости от бизнес-ситуации.

IS NULL/ IS NOT NULL условия можно напрямую вывести из полей, например: EMAIL_ADDR.IsNotNull.
```C#
ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var UR = ctx.SYS_USER_ROLE();

var data = U.InnerJoin(UR, U.USER_ACCOUNT == UR.USER_ACCOUNT, UR.STATUS == "O")
  .Where(U.STATUS == "O", U.EMAIL_ADDR.IsNotNull.Or(U.EMAIL_ADDR == "riwfnsse@163.com"), U.IS_LOCKED == "N")
  .Where(UR.ROLE_CODE.In("Administrator", "Admin", "PowerUser", "User", "Guest")) 
  .Groupby(UR.ROLE_CODE)
  .Having(U.USER_ACCOUNT.Count > 2)
  .OrderbyAsc(U.USER_ACCOUNT.Count)
  .Select(U.USER_ACCOUNT.Count.As("USER_COUNT"), UR.ROLE_CODE);

// Ниже приведён эквивалентный способ написания кода.
U.InnerJoin(UR, U.USER_ACCOUNT == UR.USER_ACCOUNT, UR.STATUS == "O");
U.Where(U.STATUS == "O");
U.Where(U.EMAIL_ADDR.IsNotNull.Or(U.EMAIL_ADDR == "riwfnsse@163.com"));
U.And(U.IS_LOCKED == "N");
U.Where(UR.ROLE_CODE.In("Administrator", "Admin", "PowerUser", "User", "Guest"));
U.Groupby(UR.ROLE_CODE);
U.Having(U.USER_ACCOUNT.Count > 2);
U.OrderbyAsc(U.USER_ACCOUNT.Count);
data = U.Select(U.USER_ACCOUNT.Count.As("USER_COUNT"), UR.ROLE_CODE);
SELECT COUNT(T0.USER_ACCOUNT) AS USER_COUNT, T1.ROLE_CODE
FROM SYS_USER T0
    INNER JOIN SYS_USER_ROLE T1
    ON T0.USER_ACCOUNT = T1.USER_ACCOUNT
        AND T1.STATUS = 'O'
WHERE T0.STATUS = 'O'
    AND (T0.EMAIL_ADDR IS NOT NULL
        OR T0.EMAIL_ADDR = 'riwfnsse@163.com')
    AND T0.IS_LOCKED = 'N'
    AND T1.ROLE_CODE IN ('Administrator', 'Admin', 'PowerUser', 'User', 'Guest')
GROUP BY T1.ROLE_CODE
HAVING COUNT(T0.USER_ACCOUNT) > 2
ORDER BY COUNT(T0.USER_ACCOUNT) ASC;

Группировка и статистика, Groupby, Having, OrderbyAsc

Методы Groupby, Having и OrderbyAsc поддерживают функции;

Count, Max, Min, Sum, Upper, Lower и другие общие встроенные функции базы данных уже включены в поля ODA. Другие функции можно использовать с помощью ODA Function.

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var UR = ctx.SYS_USER_ROLE();
var data = U.InnerJoin(UR, U.USER_ACCOUNT == UR.USER_ACCOUNT, UR.STATUS == "O")
   .Where(U.STATUS == "O", UR.ROLE_CODE.In("Administrator", "Admin", "PowerUser", "User", "Guest"))
   .Groupby(UR.ROLE_CODE)
   .Having(U.USER_ACCOUNT.Count > 2)
   .OrderbyAsc(UR.ROLE_CODE,U.USER_ACCOUNT.Count)
   .Select(U.USER_ACCOUNT.Count.As("USER_COUNT"), UR.ROLE_CODE);
SELECT COUNT(T0.USER_ACCOUNT) AS USER_COUNT, T1.ROLE_CODE
FROM SYS_USER T0
    INNER JOIN SYS_USER_ROLE T1
    ON T0.USER_ACCOUNT = T1.USER_ACCOUNT
        AND T1.STATUS = 'O'
WHERE T0.STATUS = 'O'
    AND T1.ROLE_CODE IN ('Administrator', 'Admin', 'PowerUser', 'User', 'Guest')
GROUP BY T1.ROLE_CODE
HAVING COUNT(T0.USER_ACCOUNT) > 2
ORDER BY T1.ROLE_CODE ASC, COUNT(T0.USER_ACCOUNT) ASC

IN/NOT IN условия

IN/NOT IN имеет две перегрузки: одна — массив, другая — подзапрос.

ODAContext ctx = BizContext.GetContext();
var RA = ctx.SYS_ROLE_AUTHORIZATION();
var RS = ctx.SYS_RESOURCE(); 
///IN массив
RA.Where(RA.IS_FORBIDDEN == "N", RA.STATUS == "O", RA.ROLE_CODE.In("Administrator", "Admin", "PowerUser"));

///IN подзапрос
var data = RS.Where(RS.STATUS == "O", RS.ID.In(RA, RA.RESOURCE_ID)) 
    .SelectM();
SELECT *
FROM SYS_RESOURCE T1
WHERE T1.STATUS = 'O'
    AND T1.ID IN (
        SELECT T0.RESOURCE_ID
        FROM SYS_ROLE_AUTHORIZATION T0
        WHERE T0.IS_FORBIDDEN = 'N'
            AND T0.STATUS = 'O'
            AND T0.ROLE_CODE IN ('Administrator', 'Admin', 'PowerUser')
    )

Exists/NOT Exists подзапрос

ODAContext ctx = BizContext.GetContext();
var RA = ctx.SYS_ROLE_AUTHORIZATION(); 
//Exists условие подзапроса
var RS = ctx.SYS_RESOURCE();
RA.Where(RA.IS_FORBIDDEN == "N", RA.STATUS == "C", RA.RESOURCE_ID == RS.ID); 

var data = RS.Where(RS.STATUS == "O", RS.Function.Exists(RA, RA.AllColumn)) 
    .SelectM();
SELECT *
FROM SYS_RESOURCE T1
WHERE T1.STATUS = 'O'
    AND EXISTS (
        SELECT T0.*
        FROM SYS_ROLE_AUTHORIZATION T0
        WHERE T0.IS_FORBIDDEN = 'N'
            AND T0.STATUS = 'C'
            AND T0.RESOURCE_ID = T1.ID
    )

Рекурсивный запрос

Рекурсивные запросы ODA работают аналогично Oracle StartWith ConnectBy.

Принцип работы ODA: сначала с помощью where выбираются данные, необходимые для рекурсии, а затем выполняется рекурсия в памяти.

Поскольку рекурсия выполняется в памяти, все поля, используемые в рекурсии, должны быть включены в Select. Текст запроса:

的 с как 好一个级等。

递归有深度限制,ODA 限制最大深度是31层。

被递尺的原始数据越多性能下降很快,最好保被递彺筛选的数在10W条以内.

Перевод текста запроса на русский язык:

«...с как хорошо один уровень и т. д.».

Рекурсия имеет ограничение по глубине, максимальная глубина ODA ограничена 31 уровнем.

Чем больше исходных данных подвергается рекурсии, тем быстрее снижается производительность, поэтому лучше ограничить количество данных, подвергаемых рекурсии, до 10 Вт строк. Перевод текста на русский язык:

SELECT T2.ROLE_CODE,T0.USER_ACCOUNT,COUNT(T3.RESOURCE_ID) AS ResourceCount 
FROM SYS_USER T0,SYS_USER_ROLE T1,SYS_ROLE T2,SYS_ROLE_AUTHORIZATION T3 
WHERE (T0.USER_ACCOUNT = T1.USER_ACCOUNT 
  AND T1.STATUS = 'O' 
  AND T1.ROLE_CODE = T2.ROLE_CODE 
  AND T2.STATUS = 'O' 
  AND T2.ROLE_CODE = T3.ROLE_CODE 
  AND T3.IS_FORBIDDEN = 'O' 
  AND T3.STATUS = 'O' 
  AND T0.STATUS = 'O' 
  AND (T2.ROLE_CODE = 'Administrator' OR T2.ROLE_CODE = 'Admin') 
  AND T0.IS_LOCKED = 'N') 
GROUP BY T2.ROLE_CODE,T0.USER_ACCOUNT 
HAVING COUNT(T3.RESOURCE_ID) > 10 
ORDER BY COUNT(T3.RESOURCE_ID) ASC

Обновление данных

Обычный способ обновления

Обычно оператор Update не обновляет все поля, а только указанные. Условия в операторе Update совпадают с условиями в запросе SELECT.

Пример на C#:

///Update 的 where 条件可参考 SELECT 语句 
ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
U.Where(U.LAST_UPDATED_BY == "InsertModel", U.IS_LOCKED == "N", U.STATUS == "O", U.EMAIL_ADDR.IsNotNull)
 .Update(
    U.USER_NAME == "новое имя", U.IS_LOCKED == "Y"
    );

Пример SQL:

UPDATE SYS_USER
SET USER_NAME = 'новое имя', IS_LOCKED = 'Y'
WHERE LAST_UPDATED_BY = 'InsertModel'
    AND IS_LOCKED = 'N'
    AND STATUS = 'O'
    AND EMAIL_ADDR IS NOT NULL

Обновление модели данных

При использовании сущностей для обновления данных, значения свойств, равные null, не обновляются. Это связано с тем, что в большинстве случаев при использовании ORM-компонентов, интерфейс возвращает полный объект сущности или используется как контейнер для десериализации, включая те поля, которые не требуют обновления и равны null.

Пример на C#:

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
U.Where(U.CREATED_BY == "InsertModel", U.IS_LOCKED == "N", U.STATUS == "O", U.EMAIL_ADDR.IsNotNull)
 .Update(new SYS_USER()
{
    ADDRESS = "Свободное государство", 
    CREATED_DATE = DateTime.Now, 
    STATUS = "O",
    USER_ACCOUNT = "NYear1",
    USER_NAME = "Много лет 1",
    USER_PASSWORD = "123",
    IS_LOCKED = "N",
});

Пример SQL:

UPDATE SYS_USER
SET STATUS = 'O', CREATED_DATE = '2021/10/25 14:24:34', USER_ACCOUNT = 'NYear1', USER_NAME = 'Много лет 1', USER_PASSWORD = '123', ADDRESS = 'Свободное государство', IS_LOCKED = 'N'
WHERE CREATED_BY = 'InsertModel'
    AND IS_LOCKED = 'N'
    AND STATUS = 'O'
    AND EMAIL_ADDR IS NOT NULL

Операции обновления

Поддерживаются следующие операторы: +, -, *, /, %. В настоящее время при обновлении одного поля допускается использование только одного оператора.

Пример на C#:

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER();
var data = U.Where(U.CREATED_BY == "Lambda", U.IS_LOCKED == "N", U.EMAIL_ADDR.IsNotNull)
    .Update(U.FAIL_TIMES == U.FAIL_TIMES + 1, U.USER_NAME == U.USER_ACCOUNT + U.EMAIL_ADDR ); 

Пример SQL:

UPDATE SYS_USER
SET FAIL_TIMES = FAIL_TIMES + 1, USER_NAME = USER_ACCOUNT + EMAIL_ADDR
WHERE CREATED_BY = 'Lambda'
    AND IS_LOCKED = 'N'
    AND EMAIL_ADDR IS NOT NULL

Удаление данных

Условия в операторе Delete совпадают с условиями в SELECT.

Пример на C#:

ODAContext ctx = new ODAContext();
var U = ctx.GetCmd<SysUser>();
var data = U.Where(U.USER_ACCOUNT.ContainLeft ( "User1"), U.IS_LOCKED == "N", U.EMAIL_ADDR.IsNotNull)
    .Delete();
   

Пример SQL:

DELETE FROM SYS_USER
WHERE USER_ACCOUNT LIKE 'User1%'
    AND IS_LOCKED = 'N'
    AND EMAIL_ADDR IS NOT NULL

Удаление данных

Расширенные функции после версии 1.9.0

Пример на C#:

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER_();
var data = U.Where(w=>w.CREATED_BY.ContainLeft("User2") & w.IS_LOCKED == "N" & w.EMAIL_ADDR.IsNotNull)
    .Delete();

Пример SQL:

DELETE FROM SYS_USER
WHERE (CREATED_BY LIKE 'User2%'
    AND IS_LOCKED = 'N'
    AND EMAIL_ADDR IS NOT NULL)

Цепочка обновлений данных

Расширенные функции после версии 1.9.0

Пример на C#:

ODAContext ctx = BizContext.GetContext();
var U = ctx.SYS_USER_();
var data = U.Where(w => w.CREATED_BY == "Lambda" & w.IS_LOCKED == "N" & w.EMAIL_ADDR.IsNotNull)
 .Update(v => new[] {
``` **v.FAIL_TIMES == v.FAIL_TIMES + 1, v.ADDRESS == v.USER_ACCOUNT + v.EMAIL_ADDR,v.USER_NAME == "Lambda更新" }**

 Данный фрагмент представляет собой набор выражений на языке программирования, который не удалось определить.

```SQL
UPDATE SYS_USER
SET FAIL_TIMES = FAIL_TIMES + 1, ADDRESS = USER_ACCOUNT + EMAIL_ADDR, USER_NAME = 'Lambda更新'
WHERE CREATED_BY = 'Lambda'
    AND IS_LOCKED = 'N'
    AND EMAIL_ADDR IS NOT NULL

— Это запрос на обновление данных в таблице SYS_USER в базе данных. Он устанавливает значения полей FAIL_TIMES, ADDRESS и USER_NAME для записей, где значение поля CREATED_BY равно 'Lambda', поле IS_LOCKED равно 'N', а поле EMAIL_ADDR не равно NULL.

Вставка данных

Вставка данных с указанием конкретных полей

ODAContext ctx = BizContext.GetContext();
var U = ctx.GetCmd<SysUser>();
U.Insert(U.STATUS == "O", U.CREATED_BY == "Insert", U.LAST_UPDATED_BY == "User1", U.LAST_UP-DATED_DATE == DateTime.Now, U.CREATED_DATE == DateTime.Now, U.EMAIL_ADDR == "riwfnsse@163.com",
    U.USER_ACCOUNT == "MYEAR_Insert", U.USER_NAME == "多年", U.USER_PASSWORD == "123", U.FE_MALE == "M", U.FAIL_TIMES == 0, U.IS_LOCKED == "N");
INSERT INTO SYS_USER (STATUS, CREATED_BY, LAST_UPDATED_BY, LAST_UPDATED_DATE, CREATED_DATE
    , EMAIL_ADDR, USER_ACCOUNT, USER_NAME, USER_PASSWORD, FE_MALE
    , FAIL_TIMES, IS_LOCKED)
VALUES ('O', 'Insert', 'User1', '2021/10/25 14:36:04', '2021/10/25 14:36:04'
    , 'riwfnsse@163.com', 'MYEAR_Insert', '多年', '123', 'M'
    , 0, 'N')

— В этом фрагменте кода на языке C# используется метод Insert для вставки новой записи в таблицу SYS_USER. Значения полей STATUS, CREATED_BY и других задаются с помощью логических выражений. В запросе SQL также выполняется вставка новой записи с указанными значениями полей.

Вставка модели данных

ODAContext ctx = BizContext.GetContext();
var U = ctx.GetCmd<SysUser>();
U.Insert(new SYS_USER()
{
    ADDRESS = "自由国度",
    CREATED_BY = "InsertModel",
    CREATED_DATE = DateTime.Now,
    FAIL_TIMES = 0,
    STATUS = "O",
    USER_ACCOUNT = "MYEAR_Model1122",
    USER_NAME = "多年1",
    USER_PASSWORD = "123",
    IS_LOCKED = "N",
    EMAIL_ADDR = "riwfnsse@163.com"
});
INSERT INTO SYS_USER (STATUS, CREATED_BY, CREATED_DATE, USER_ACCOUNT, USER_NAME
    , USER_PASSWORD, EMAIL_ADDR, ADDRESS, FAIL_TIMES, IS_LOCKED)
VALUES ('O', 'InsertModel', '2021/10/25 14:39:21', 'MYEAR_Model1122', '多年1'
    , '123', 'riwfnsse@163.com', '自由国度', 0, 'N')

— Здесь также используется метод Insert, но на этот раз для вставки модели данных SYS_USER с заданными значениями полей. В запросе SQL выполняется аналогичная операция.

Цепная вставка данных

ODAContext ctx = BizContext.GetContext();
var U = ctx.From<SysUser>();
U.Insert(a => new[]{a.ADDRESS == "自由国度",a.CREATED_BY =="Lambda", a.USER_NAME=="Lambda",a.CREATED_DATE == DateTime.Now, a.EMAIL_ADDR=="riwfnsse@163.com",
    a.FAIL_TIMES == 0,a.STATUS =="O",a.USER_ACCOUNT=="MYear1" + Guid.NewGuid().ToString("N"),a.USER_PASSWORD=="123",a.IS_LOCKED =="N"}
    );
INSERT INTO SYS_USER (ADDRESS, CREATED_BY, USER_NAME, CREATED_DATE, EMAIL_ADDR
    , FAIL_TIMES, STATUS, USER_ACCOUNT, USER_PASSWORD, IS_LOCKED)
VALUES ('自由国度', 'Lambda', 'Lambda', '2021/10/25 14:40:32', 'riwfnsse@163.com'
    , 0, 'O', 'MYear1fbbf0613ba2f44199b520ea93d40a594', '123', 'N')

— Этот фрагмент кода также использует метод Insert, но здесь применяется цепная запись условий для вставки данных. В запросе SQL выполняются аналогичные операции.

Массовая загрузка данных

В этом разделе описывается процесс массовой загрузки данных в базу данных с использованием DataTable. Однако текст не содержит подробностей о том, как именно это делается. Обычно, чем больше система, тем более ценными являются ресурсы базы данных, и тем осторожнее следует применять транзакции.

Не стоит использовать транзакции там, где можно без них обойтись. Если возможно, сократите количество DML-операций в транзакциях, а также время выполнения транзакций.

Поскольку объекты базы данных блокируются до завершения транзакции, и только один пользователь может заблокировать объект одновременно, транзакции могут снижать параллельную производительность системы. Длительная блокировка объектов базы данных или возникновение ситуаций ожидания блокировки или взаимоблокировки могут иметь фатальные последствия для системы.

  ODAContext ctx = new ODAContext();
  var U1 = ctx.GetCmd<SysUser>();
  ctx.BeginTransaction();
  try
  {
      var U = ctx.GetCmd<SysUser>();
      U.Where(U.USER_ACCOUNT == "User1", U.IS_LOCKED == "N", U.STATUS == "O", U.EMAIL_ADDR.IsNotNull)
      .Update(U.USER_NAME == "новое имя", U.IS_LOCKED == "Y"); 
      U1.Insert(U.STATUS == "O", U.USER_NAME == "User1", U.LAST_UPDATED_BY == "User1", U.LAST_UPDATED_DATE == DateTime.Now, U.CREATED_DATE == DateTime.Now,U.USER_ACCOUNT == "Nyear", U.USER_NAME == "много лет", U.USER_PASSWORD == "123", U.FE_MALE == "M", U.FAIL_TIMES == 0, U.IS_LOCKED == "N");
       ctx.Commit();
   }
   catch
   {
      ctx.RollBack();
   }

Функции

База данных функций

ODA предоставляет набор общих системных функций, которые часто используются в базах данных: MAX, MIN, COUNT, SUM, AVG, LENGTH, LTRIM, RTRIM, TRIM, ASCII, UPPER, LOWER. Эти функции вызываются непосредственно из полей, например: USER_ACCOUNT.Count.

ODAContext ctx = new ODAContext();
var U = ctx.GetCmd<SysUser>();
object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
       .Groupby(U.USER_ACCCOUNT)
       .Select(U.Function.Count.As("CountAll"), U.USER_ACCOUNT.Count.As("CountOne"), U.USER_ACCOUNT.Upper.As("UPPER_ACC"), U.USER_ACCOUNT.Trim.Ltrim.As("TRIM_ACC"));
SELECT COUNT(*) AS CountAll,
       COUNT(T0.USER_ACCOUNT) AS CountOne,
       UPPER(T0.USER_ACCOUNT) AS UPPER_ACC,
       LTRIM(T0.USER_ACCOUNT) AS TRIM_ACC
  FROM SYS_USER T0
 WHERE T0.STATUS = 'O'
   AND T0.IS_LOCKED = 'N'
 GROUP BY T0.USER_ACCOUNT;       

Выражение

Express метод позволяет разработчикам внедрять свои собственные SQL-скрипты в SELECT-поля. Поскольку выражения ODA представляют собой внедренные SQL-запросы, разработчики должны быть осторожны с рисками SQL-инъекций и возможностью использования выражений в разных базах данных.

ODAParameter p1 = new ODAParameter() { ColumnName = "Params1", DBDataType = ODAdbType.OVarchar, Direction = System.Data.ParameterDirection.Input, ParamsName = ODAParameter.ODAParamsMark + "Params1", ParamsValue = "Я первый параметр", Size = 2000 };
 ODAParameter p2 = new ODAParameter() { ColumnName = "Params2", DBDataType = ODAdbType.OVarchar, Direction = System.Data.ParameterDirection.Input, ParamsName = ODAParameter.ODAParamsMark + "Params2", ParamsValue = "Это SQL-инъекция", Size = 2000 };
ODAContext ctx = new ODAContext();
var U = ctx.GetCmd<SysUser>();
object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
       .Select(U.Function.Express("1+1").As("COMPUTED"),
        U.Function.Express(" null ").As("NULL_COLUMN"), 
        U.Function.Express(" 'Function( + " + ODAParameter.ODAParamsMark + "Params1, " + ODAParameter.ODAParamsMark + "Params2)' ", p1, p2).As("SQL_Injection"));
 
SELECT 1 + 1 AS COMPUTED,
       null AS NULL_COLUMN,
       'Function( + @Params1, @Params2)' AS SQL_Injection
  FROM SYS_USER T0
 WHERE T0.STATUS = @T1
   AND T0.IS_LOCKED = @T2;

Виртуальные поля, временные поля

VisualColumn метод представляет собой еще одну оболочку для Express метода, предоставляя разработчикам удобство и избегая необходимости преобразования данных и рисков SQL-инъекции.

 ODAContext ctx = new ODAContext();
var U = ctx.GetCmd<SysUser>();
object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
      .Select(U.Function.VisualColumn("HELLO , I am MYear software").As("STRING_COLUMN"), U.Function.VisualColumn(DateTime.Now).As("APPLICATION_DATETIME"), U.Function.VisualColumn(0).As("DIGIT_COLUMN"));
SELECT 'HELLO , I am MYear software' AS STRING_COLUMN,
       @T1 AS APPLICATION_DATETIME,
       0 AS DIGIT_COLUMN
  FROM SYS_USER T0
 WHERE T0.STATUS = 'O'
   AND T0.IS_LOCKED = 'N';

Пользовательские функции

CreateFunc метод позволяет добавлять пользовательские функции в SELECT поля. Однако, поскольку разные базы данных имеют значительные различия в вызове пользовательских функций, ODA не может обеспечить их универсальность. Поэтому, если требуется использование CreateFunc метода в разных базах данных, необходимо учитывать особенности схемы, пользователя, владельца базы данных и других объектов при создании базы данных.

ODAContext ctx = new ODAContext();
var RS = ctx.GetCmd<SysResource>();
object data = RS.Where(RS.STATUS == "O",RS.RESOURCE_TYPE =="MENU") 
       .Select(RS.AllColumn,RS.Function.CreateFunc("dbo.GET_RESOURCE_PATH", RS.ID).As("RESOURCE_PATH"));
 SELECT T0.*,dbo.GET_RESOURCE_PATH(T0.ID) AS RESOURCE_PATH 
 FROM SYS_RESOURCE T0 
 WHERE T0.STATUS = 'O' AND T0.RESOURCE_TYPE = 'MENU';

Преобразование данных CaseWhen

SQL-оператор: case when условие. Тогда значение, когда условие, иначе значение по умолчанию

ODAContext ctx = new ODAContext();  
var U = ctx.GetCmd<SysUser>();
Dictionary<ODAColumns, object> Addr = new Dictionary<ODAColumns, object>();
Addr.Add(U.ADDRESS.IsNull, "无用户地址数据...");
Addr.Add(U.ADDRESS.Like("%公安局%"), "被抓了?");

Dictionary<ODAColumns, object> phone = new Dictionary<ODAColumns, object>();
phone.Add(U.PHONE_NO.IsNull, "Этот человек очень ленив и ничего не оставил");
phone.Add(U.PHONE_NO == "110", "Маленький вор, беги!");
phone.Add(U.ADDRESS.NotLike("%公安局%"), "Был пойман?");

object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
       .Select(U.Function.CaseWhen(Addr, U.ADDRESS).As("ADDRESS"), U.Function.CaseWhen(phone, "110").As("PHONE_NO"));
--------------------------------

            ODAContext ctx = BizContext.GetContext();
            var U = ctx.SYS_USER();

            object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
                 .Select(U.CaseWhen(U.ADDRESS.IsNull).Then("无用户地址数据..")
                 .When(U.ADDRESS.Like("%公安局%")).Then("Был пойман?")
                 .Else(U.ADDRESS).End().As("ADDRESS"),
                 U.CaseWhen(U.PHONE_NO.IsNull).Then("Этот человек очень ленив и ничего не оставил")
                 .When(U.PHONE_NO == "110").Then("Маленький вор, беги!")
                 .When(U.ADDRESS.NotLike("%公安局%")).Then("Был пойман?")
                 .Else(U.ADDRESS).End().As("PHONE_NO"));
            return data;

Выбор значений на основе условий

SELECT CASE 
        WHEN T0.ADDRESS IS NULL THEN '无用户地址数据...'
        WHEN T0.ADDRESS LIKE '%公安局%' THEN 'Был пойман?'
        ELSE T0.ADDRESS
    END AS ADDRESS
    , CASE 
        WHEN T0.PHONE_NO IS NULL THEN 'Этот человек очень ленив и ничего не оставил'
        WHEN T0.PHONE_NO = '110' THEN 'Маленький вор, беги!'
        WHEN T0.ADDRESS NOT LIKE '%公安局%' THEN 'Был пойман'
        ELSE '110'
    END AS PHONE_NO
FROM SYS_USER T0
WHERE T0.STATUS = 'O'
    AND T0.IS_LOCKED = 'N';
--------------------
SELECT ( CASE  WHEN T0.ADDRESS IS NULL  THEN '无用户地址数据..' WHEN T0.ADDRESS LIKE '%公安局%' THEN 'Был пойман?' ELSE T0.ADDRESS END ) AS ADDRESS,
( CASE  WHEN T0.PHONE_NO IS NULL  THEN 'Этот человек очень ленив и ничего не оставил' WHEN T0.PHONE_NO = '110' THEN 'Маленький вор, беги!' WHEN T0.ADDRESS NOT LIKE '%公安局%' THEN 'Был пойман?' ELSE '110' END ) AS PHONE_NO 
FROM SYS_USER T0 
WHERE T0.STATUS = 'O' 
AND T0.IS_LOCKED = 'N'

Обработка пустых значений

NullDefault — это повторная упаковка метода CaseWhen для удобства использования.

ODAContext ctx = new ODAContext();
var U = ctx.GetCmd<SysUser>();
object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
       .Select(U.Function.NullDefault(U.ADDRESS, "无用户地址数据...").As("ADDRESS"), U.Function.NullDefault(U.PHONE_NO,110).As("PHONE_NO"));

------          
ODAContext ctx = BizContext.GetContext();
            var U = ctx.SYS_USER();
            object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
                 .Select(U.Address.NullDefault("无用户地址数据...").As("ADDRESS"), U.PhoneNo.NullDefault(110).As("PHONE_NO"));
            return data;
SELECT (CASE
         WHEN T0.ADDRESS IS NULL THEN
          '无用户地址数据...'
         ELSE
          T0.ADDRESS
       END) AS ADDRESS,
       (CASE
         WHEN T0.PHONE_NO IS NULL THEN
          110
         ELSE
          T0.PHONE_NO
       END) AS PHONE_NO
  FROM SYS_USER T0
 WHERE T0.STATUS = 'O'
   AND T0.IS_LOCKED = 'N';

------

SELECT ( CASE  WHEN T0.ADDRESS IS NULL  THEN '无用户地址数据...' ELSE T0.ADDRESS END ) AS ADDRESS,
( CASE  WHEN T0.PHONE_NO IS NULL  THEN 110 ELSE T0.PHONE_NO END ) AS PHONE_NO 
FROM SYS_USER T0 
WHERE T0.STATUS = 'O' 
AND T0.IS_LOCKED = 'N'

Преобразование данных с использованием Case

В SQL оператор case используется для сравнения значения поля с заданным значением и возврата другого значения в случае совпадения.

ODAContext ctx = new ODAContext();
var U = ctx.GetCmd<SysUser>();

Dictionary<object, object> Addr = new Dictionary<object, object>();
Addr.Add(U.Function.Express(" NULL "), "无用户地址数据...");
Addr.Add("天堂", "人生最终的去处");
Dictionary<object, object> phone = new Dictionary<object, object>();
phone.Add(U.Function.Express(" NULL "), "Этот человек очень ленив и ничего не оставил");
phone.Add( "110", "Маленький вор, беги!");
phone.Add(U.ADDRESS, "Данные ошибочны, телефон и адрес совпадают");

object data = U.Where(U.STATUS == "O", U.IS_LOCKED == "N")
       .Select(U.Function.Case(U.ADDRESS,Addr, U.ADDRESS).As("ADDRESS"), U.Function.Case(U.PHONE_NO,phone, U.PHONE_NO).As("PHONE_NO");
``` **Данные содержания преобразования Case**

SQL-оператор CASE позволяет выбрать одно из нескольких значений в зависимости от условия. В данном случае оператор используется для обработки полей T0.ADDRESS и T0.PHONE_NO. Если значение поля равно NULL, то возвращается строка «无用户地址数据...». Если значение поля T0.ADDRESS равно «天堂», то возвращается «人生最终的去处». В противном случае возвращается значение самого поля.

Для поля T0.PHONE_NO при значении «110» возвращается значение поля T0.ADDRESS, при значении «119»  «拿水来», в остальных случаях возвращается значение самого поля T0.PHONE_NO.

Запрос выбирает данные из таблицы SYS_USER, где статус равен «O», а IS_LOCKED равен «N». Для выбранных данных выполняется преобразование полей ADDRESS и PHONE_NO с использованием оператора CASE.

**Данные содержания преобразования Decode**

Метод ODAContext.Decode используется для преобразования значений полей в соответствии с заданными условиями. Метод принимает три параметра: исходное значение, значение по умолчанию и список пар ключ-значение. Если исходное значение совпадает с одним из ключей, то в качестве результата возвращается соответствующее значение из пары. В противном случае в качестве результата возвращается значение по умолчанию.

В запросе метод используется для преобразования поля RESOURCE_TYPE в таблице SYS_RESOURCE. Если значение поля совпадает с одним из заданных ключей, то в результате возвращается соответствующее значение. В противном случае возвращается значение «未知类型».

Запрос выбирает данные из таблицы SYS_RESOURCE, где статус равен «О», а тип ресурса равен «MENU». Для выбранного значения поля RESOURCE_TYPE выполняется преобразование с использованием метода ODAContext.Decode. **Текст запроса:**

DataColumn("STATUS"));  
data.Columns.Add(new DataColumn("DUMMY"));  
data.Columns.Add(new DataColumn("USER_ACCOUNT"));  
data.Columns.Add(new DataColumn("USER_NAME"));  
data.Columns.Add(new DataColumn("USER_PASSWORD"));  
data.Columns.Add(new DataColumn("IS_LOCKED"));  
for (int i = 0; i < 10000; i++)  
{  
    object[] dr = new object[]  
    {  
        "自由国度",  
        "User1" ,  
        DateTime.Now,  
        "riwfnsse@163.com",  
        "User1" ,  
        DateTime.Now,  
        0,  
        "O",  
        "Dummy",  
        "ImportUser" + i.ToString(),  
        "导入的用户" + i.ToString(),  
        "123",  
        "N"  
      };  
    data.Rows.Add(dr);  
}  
List<SYS_USER> DataList = ODA.DBAccess.ConvertToList<SYS_USER>(data);

**Перевод текста на русский язык:**

ДатаКолоун («СТАТУС»);  
дата.Колумнс.Адд (новый ДатаКолоун («ДАММИ»));  
дата.Колумнс.Адд (новый ДатаКолоун («УСЕР_АКАУНТ»));  
дата.Колумнс.Адд (новый ДатаКолоун («УСЕР_НАМЕ»));  
дата.Колумнс.Адд (новый ДатаКолоун («УСЕР_ПАССВОРД»));  
дата.Колумнс.Адд (новый ДатаКолоун («ИС_ЛОКЭД»));  
фор (инт я = 0; я < 10000; я++)  
{  
    объект[] др = новый объект[]  
    {  
        «свободный государство»,  
        «Усер1»,  
        ДатаТим.Нау,  
        «риуфнсэ@163 точка ком»,  
        «Усер1»,  
        ДатаТим.Нау,  
        0,  
        «О»,  
        «Дамми»,  
        «ИмпортУсер» + я.ТоСтрока,  
        «импортный пользователь» + я.ТоСтрока,  
        «123»,  
        «Н»  
    };  
    дата.Роус.Адд (др);  
}  
Лист<СИС_УСЕР> ДатаЛист = ОДА.ДБАКцесс.КонвертТол<СИС_УСЕР>(дата); Третий  это инструмент для копирования данных из одной таблицы в другой базе данных.

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Описание недоступно Развернуть Свернуть
MIT
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/riwfnsse-MYear.ODA.git
git@api.gitlife.ru:oschina-mirror/riwfnsse-MYear.ODA.git
oschina-mirror
riwfnsse-MYear.ODA
riwfnsse-MYear.ODA
master