private void fillDataSetWithChildFoldersWithUpdatedState(XStorageConnection con, DomainObjectDataSet dataSet, Guid objectID, FolderStates folderState) { // зачитаем идентификаторы всех подчиненных папок, состояние которых отличается от требуемого XDbCommand cmd = con.CreateCommand(@" SELECT f.ObjectID FROM Folder f_s WITH(NOLOCK) JOIN Folder f WITH(NOLOCK) ON f.LIndex > f_s.LIndex AND f.RIndex < f_s.RIndex AND f.Customer = f_s.Customer WHERE f_s.ObjectID = @ObjectID AND f.State <> @TargetState " ); // закрытие закрывает все вложенные папки без учета их состояния: // if (folderState == FolderStates.Closed) - Nothing to do // замораживание замораживает открытые и ожидающие закрытия if (folderState == FolderStates.Frozen) { cmd.CommandText = cmd.CommandText + " AND f.State IN (" + FolderStatesItem.Open.IntValue + "," + FolderStatesItem.WaitingToClose.IntValue + ")"; } // перевод в "ожидание закрытие" применим только для открытых (т.е. замороженные и закрытые не трогаются) //else if (folderState == FolderStates.WaitingToClose) //cmd.CommandText = cmd.CommandText + " AND f.State = " + FolderStatesItem.Open.IntValue; cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, objectID); cmd.Parameters.Add("TargetState", DbType.Int16, ParameterDirection.Input, false, (Int16)folderState); using (IDataReader reader = cmd.ExecuteReader()) { DomainObjectData xobjSubFolder; while (reader.Read()) { xobjSubFolder = dataSet.GetLoadedStub("Folder", reader.GetGuid(0)); xobjSubFolder.SetUpdatedPropValue("State", folderState); } } }
/// <summary> /// Возвращает строку из емейлов, считанных из первой колонки результата выполнения переданной команды /// ВНИМАНИЕ: В список емейлов не включается емейл текущего пользователя /// </summary> /// <param name="cmd"></param> /// <returns></returns> private string readEMails(XDbCommand cmd) { StringBuilder bld = new StringBuilder(); ITUser user = (ITUser)XSecurityManager.Instance.GetCurrentUser(); string sIgnore = null; if (user.EMail != null && user.EMail.Length > 0) { sIgnore = user.EMail; } using (IDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { if (!reader.IsDBNull(reader.GetOrdinal("EMail"))) { string sEmail = reader.GetString(reader.GetOrdinal("EMail")); if (!sEmail.Equals(sIgnore)) { if (bld.Length > 0) { bld.Append(";"); } bld.Append(sEmail); } } } } return(bld.ToString()); }
private void UpdateChildDepartments(XStorageConnection con, DomainObjectDataSet dataSet, Guid objectID, bool IsArchive) { // Обновляем вложенные департаменты, если мы меняем признак на "Архивный". // Если признак "Архивный" снимается, каскадной разархивации не происходит. // зачитаем идентификаторы всех подчиненных департаментов, состояние которых отличается от требуемого if (IsArchive) { XDbCommand cmd = con.CreateCommand(@" SELECT d.ObjectID FROM dbo.Department as d_s WITH(NOLOCK) JOIN dbo.Department as d WITH(NOLOCK) ON d.LIndex > d_s.LIndex AND d.RIndex < d_s.RIndex AND d.Organization = d_s.Organization WHERE d_s.ObjectID = @ObjectID AND d.IsArchive <> @IsArchive " ); cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, objectID); cmd.Parameters.Add("IsArchive", DbType.Boolean, ParameterDirection.Input, false, IsArchive); using (IDataReader reader = cmd.ExecuteReader()) { DomainObjectData xobjSubDepartment; while (reader.Read()) { xobjSubDepartment = dataSet.GetLoadedStub("Department", reader.GetGuid(0)); xobjSubDepartment.SetUpdatedPropValue("IsArchive", IsArchive); } } } }
private static List <string> GetMemoTableList(XDbConnection con) { List <string> lst = new List <string>(); DataTable dt = new DataTable(); string commandString = string.Format("Exec SP_COLUMNS_EX N'{0}'", XDbEnvironment.CalculateLinkedSrvName(con.InputFile)); using (DbCommand comm = new XDbCommand(commandString, con)) { using (DbDataReader reader = comm.ExecuteReader()) { dt.Load(reader, LoadOption.OverwriteChanges); } // Go through the table rows and search for the memo fields( TYPE_NAME = VarChar && COLUMN_SIZE = 0 ) foreach (DataRow row in dt.Rows) { if ((row["TYPE_NAME"].ToString() == "VarChar") && (row["COLUMN_SIZE"].ToString() == "0")) { if (!lst.Contains(row["TABLE_NAME"].ToString())) { lst.Add(row["TABLE_NAME"].ToString()); } } } } return(lst); }
private DomainObjectData loadFolderAndIncident(DomainObjectDataSet dataSet, GetMailMsgInfoRequest request, IXExecutionContext context) { DomainObjectData xobjFolder; if (request.ObjectType == "Folder") { xobjFolder = dataSet.GetLoadedStub("Folder", request.ObjectID); dataSet.LoadProperty(context.Connection, xobjFolder, "Name"); } else { XDbCommand cmd = context.Connection.CreateCommand( @"SELECT f.ObjectID as FolderID, f.Name as FolderName, i.Name as IncidentName, i.Number as IncidentNumber FROM Incident i JOIN Folder f ON i.Folder=f.ObjectID WHERE i.ObjectID = @IncidentID" ); cmd.Parameters.Add("IncidentID", DbType.Guid, ParameterDirection.Input, false, request.ObjectID); DomainObjectData xobjIncident = dataSet.GetLoadedStub("Incident", request.ObjectID); using (IDataReader reader = cmd.ExecuteReader()) { if (!reader.Read()) { throw new XObjectNotFoundException("Incident", request.ObjectID); } xobjFolder = dataSet.GetLoadedStub("Folder", reader.GetGuid(reader.GetOrdinal("FolderID"))); xobjFolder.SetLoadedPropValue("Name", reader.GetString(reader.GetOrdinal("FolderName"))); xobjIncident.SetLoadedPropValue("Name", reader.GetString(reader.GetOrdinal("IncidentName"))); xobjIncident.SetLoadedPropValue("Number", reader.GetInt32(reader.GetOrdinal("IncidentNumber"))); xobjIncident.SetLoadedPropValue("Folder", xobjFolder.ObjectID); } } return(xobjFolder); }
/// <summary> /// Команда получения данных для фильтра списка тендеров /// </summary> public GetFilterTendersInfoResponse Execute(GetFilterTendersInfoRequest request, IXExecutionContext context) { GetFilterTendersInfoResponse resp = new GetFilterTendersInfoResponse(); using (XDbCommand cmd = context.Connection.CreateCommand()) { // Если идентификатор тендера не задан if (request.SelectedTenderID == Guid.Empty) { cmd.CommandText = @"SELECT TOP 1 ObjectID FROM dbo.Organization with (nolock) WHERE Home <> 0" ; object temp = cmd.ExecuteScalar(); resp.OrganizationID = (temp == null) ? Guid.Empty : (Guid)temp; } // Если задан else { cmd.CommandText = @"SELECT TOP 1 O.ObjectID, T.DocFeedingDate FROM dbo.Tender AS T with (nolock) LEFT JOIN dbo.Lot AS L with (nolock) ON L.Tender = T.ObjectID LEFT JOIN dbo.LotParticipant AS P with (nolock) ON P.Lot = L.ObjectID LEFT JOIN dbo.Organization AS O with (nolock) ON O.ObjectID = P.ParticipantOrganization WHERE O.OwnTenderParticipant <> 0 AND T.ObjectID = @SelectedTenderID" ; // Передадим в параметр ID тендера cmd.Parameters.Add("SelectedTenderID", DbType.Guid, ParameterDirection.Input, false, request.SelectedTenderID); using (IDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { // Проставим значения ID огранизации и "даты подачи документов" resp.OrganizationID = reader.IsDBNull(0) ? Guid.Empty : reader.GetGuid(0); resp.DocFeedingDate = reader.IsDBNull(1) ? DateTime.MinValue : reader.GetDateTime(1); } else { resp.OrganizationID = Guid.Empty; resp.DocFeedingDate = DateTime.MinValue; } } } } return(resp); }
/// <summary> /// Возвращает полный путь до инцидента, заданного идентификатором, либо номером /// </summary> /// <param name="con"></param> /// <param name="IncidentNumber">номер инцидента</param> /// <param name="IncidentOID">идентификатор инцидента или Guid.Empty</param> /// <returns></returns> private XTreePath GetIncidentFullPath(XStorageConnection con, Int32 IncidentNumber, Guid IncidentOID) { Guid organizationID = Guid.Empty; // идентификатор организации, в которой расположен инцидент Guid activityTypeID = Guid.Empty; // идентификатор вида активности,на которую ссылается папка, в которой разположен инцидент // сфомируем путь из каталогов string sQuery = String.Format( @"SELECT i.ObjectID AS IncidentID, f.ObjectID, f_s.Customer, f_s.ActivityType FROM Incident i with (nolock) JOIN Folder f_s with (nolock) ON i.Folder = f_s.ObjectID JOIN Folder f with (nolock) ON f.LIndex <= f_s.LIndex AND f.RIndex >= f_s.RIndex AND f.Customer = f_s.Customer WHERE {0} ORDER BY f.LRLevel DESC" , IncidentOID == Guid.Empty ? "i.Number = @Number" : "i.ObjectID = @ObjectID" ); XDbCommand cmd = con.CreateCommand(sQuery); if (IncidentOID == Guid.Empty) { cmd.Parameters.Add("Number", DbType.Int32, ParameterDirection.Input, false, IncidentNumber); } else { cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, IncidentOID); } XTreePath path = new XTreePath(); // путь using (IDataReader reader = cmd.ExecuteReader()) { int nObjectIDIndex = -1; // индекс поля ObjectID while (reader.Read()) { if (nObjectIDIndex < 0) { // первая итерация IncidentOID = reader.GetGuid(reader.GetOrdinal("IncidentID")); organizationID = reader.GetGuid(reader.GetOrdinal("Customer")); activityTypeID = reader.GetGuid(reader.GetOrdinal("ActivityType")); nObjectIDIndex = reader.GetOrdinal("ObjectID"); } path.Append(TYPE_Folder, reader.GetGuid(nObjectIDIndex)); } } if (path.Length > 0) { path.Append(GetPathToFolder(con, organizationID, activityTypeID)); path.InsertAtBeginning(TYPE_Incident, IncidentOID); } return(path); }
private DataTable GetDataTable(string sql) { if (!IsConnectionValid) { return(null); } using (DbCommand cmd = new XDbCommand(sql, m_XDbConnection)) { using (DbDataReader rd = cmd.ExecuteReader()) { DataTable data = new DataTable(); data.Load(rd); return(data); } } }
/// <summary> /// Метод получения идентификатора объекта "Сотрудник" по идентификатору объекта "Пользователь приложения" /// </summary> private Guid getEmployeeID(XStorageConnection con, Guid objectID) { Guid uidEmployeeID = Guid.Empty; // идентификатор сотрудника // Зачитаем идентификатор XDbCommand cmd = con.CreateCommand(@"SELECT e.ObjectID FROM [dbo].[Employee] e JOIN [dbo].[SystemUser] su ON e.SystemUser = su.ObjectID WHERE su.ObjectID = @ObjectID "); cmd.Parameters.Add("ObjectID", DbType.Guid, ParameterDirection.Input, false, objectID); using (IDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { uidEmployeeID = reader.GetGuid(0); } } return(uidEmployeeID); }
public GetKassBallanceResponse Execute(GetKassBallanceRequest request, IXExecutionContext context) { using (XDbCommand cmd = context.Connection.CreateCommand()) { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "[dbo].[app_GetKassBallance]"; GetKassBallanceResponse response = new GetKassBallanceResponse(); using (IDataReader reader = cmd.ExecuteReader()) { if (0 != reader.FieldCount) { while (reader.Read()) { response.sKassBallance = reader.GetString(0); } } return(response); } } }
/// <summary> /// Возвращает полный путь к проекту: Folder|oid|..|Folder|{oid}|ActivitType|{oid}|Organization|{oid} /// </summary> /// <param name="con"></param> /// <param name="FolderExID">Код проекта</param> /// <returns></returns> public XTreePath GetFolderFullPath(XStorageConnection con, string FolderExID) { // сфомируем путь из каталогов XDbCommand cmd = con.CreateCommand(@" SELECT f.ObjectID, f.Customer, f_s.ActivityType FROM Folder f_s with (nolock) JOIN Folder f with (nolock) ON f.LIndex <= f_s.LIndex AND f.RIndex >= f_s.RIndex AND f.Customer = f_s.Customer WHERE f_s.ExternalID = @FolderExID ORDER BY f.LRLevel DESC" ); cmd.Parameters.Add("FolderExID", DbType.String, ParameterDirection.Input, false, FolderExID); XTreePath path = new XTreePath(); // путь Guid organizationID = Guid.Empty; // идентификатор организации, в которой расположен инцидент Guid activityTypeID = Guid.Empty; // идентификатор вида активности,на которую ссылается папка, в которой разположен инцидент using (IDataReader reader = cmd.ExecuteReader()) { int nObjectIDIndex = -1; // индекс поля ObjectID while (reader.Read()) { if (nObjectIDIndex < 0) { organizationID = reader.GetGuid(reader.GetOrdinal("Customer")); activityTypeID = reader.GetGuid(reader.GetOrdinal("ActivityType")); nObjectIDIndex = reader.GetOrdinal("ObjectID"); } path.Append(TYPE_Folder, reader.GetGuid(nObjectIDIndex)); } } // Сформируем путь из организаций и типов проектных затрат if (path.Length > 0) { XTreePath pathToFolder = GetPathToFolder(con, organizationID, activityTypeID); path.Append(pathToFolder); } return(path); }
/// <summary> /// Конструирует описание пользователя по наименованию. /// Если пользователя с таким наименованием не найдено, то возвращает null /// </summary> /// <param name="sUserName">Наименование пользователя</param> /// <returns></returns> public XUser CreateUser(string sUserName) { ITUser user; using (XStorageConnection con = getConnection()) { con.Open(); XDbCommand cmd = con.CreateCommand(); cmd.CommandText = /* Получим описание пользователя (который может быть сотрудником), * системные привилегии (как выданные явно, так и полученные через роли). * Примечания: - пользователь приложения может не быть сотрудником. * - для пользователя приложения могут быть не заданы роли * - GetWorkdayDuration возвращает количество минут * */ @"SELECT su.ObjectID AS SysUserID, su.IsAdmin, su.IsServiceAccount, emp.ObjectID AS EmpID, emp.LastName, emp.FirstName, emp.EMail, su.SystemPrivileges, sr.Name as RoleName, sr.Description as RoleDescription, sr.Priviliges as RolePrivileges, dbo.GetWorkdayGlobalDuration() as WorkingMinutesInDay, CASE WHEN emp.WorkEndDate < getDate() THEN 0 ELSE 1 END as AccessPermitted FROM SystemUser su WITH (nolock) LEFT JOIN Employee emp WITH (nolock) ON emp.SystemUser = su.ObjectID LEFT JOIN (SystemUser_SystemRoles su_sr WITH (nolock) JOIN SystemRole sr WITH (nolock) ON su_sr.Value = sr.ObjectID ) ON su.ObjectID = su_sr.ObjectID WHERE su.Login = @UserLogin"; cmd.Parameters.Add("UserLogin", DbType.String, ParameterDirection.Input, false, sUserName); using (IDataReader reader = cmd.ExecuteReader()) { XRole[] roles; // массив системных ролей Guid SystemUserID; // идентификатор пользователя Guid EmployeeID = Guid.Empty; // идентификатор сотрудника string sLastName = null; // фамилия сотрудника string sFirstName = null; // имя сотрудника string sEMail = null; // email сотрудника bool bIsAdmin; // признак админа (необграниченного пользователя) bool bIsServiceAccount; // признак сервисного аккаунта int nIndex; // временная - индекс колонки int nPrivileges; // числовая маска привилегий (в БД привилегии лежат как флаги) int nWorkingMinutesInDay; // количество рабочих часов в сутках bool bAccesssPermitted = true; if (reader.Read()) { // получим маску привилегий, выданных пользователю явно nPrivileges = reader.GetInt32(reader.GetOrdinal("SystemPrivileges")); // поле SystemPrivileges - not null SystemUserID = reader.GetGuid(reader.GetOrdinal("SysUserID")); bIsAdmin = reader.GetBoolean(reader.GetOrdinal("IsAdmin")); bIsServiceAccount = reader.GetBoolean(reader.GetOrdinal("IsServiceAccount")); nWorkingMinutesInDay = reader.GetInt32(reader.GetOrdinal("WorkingMinutesInDay")); nIndex = reader.GetOrdinal("EmpID"); if (!reader.IsDBNull(nIndex)) { // если пользователь является сотрудником EmployeeID = reader.GetGuid(nIndex); sLastName = reader.GetString(reader.GetOrdinal("LastName")); sFirstName = reader.GetString(reader.GetOrdinal("FirstName")); bAccesssPermitted = reader.GetInt32(reader.GetOrdinal("AccessPermitted")) == 1; nIndex = reader.GetOrdinal("EMail"); if (!reader.IsDBNull(nIndex)) { sEMail = reader.GetString(nIndex); } } } else { // не нашли пользователя return(CreateAnonymousUser()); } // зачитаем все роли текущего юзера ArrayList aRoles = new ArrayList(); // список объектов XRole - роли пользователя int nIndex_RoleName = reader.GetOrdinal("RoleName"); int nIndex_RoleDescription = reader.GetOrdinal("RoleDescription"); int nIndex_RolePrivileges = reader.GetOrdinal("RolePrivileges"); if (!reader.IsDBNull(nIndex_RoleName)) { // по всем ролям пользователя do { string sDescription = String.Empty; if (!reader.IsDBNull(nIndex_RoleDescription)) { sDescription = reader.GetString(nIndex_RoleDescription); } // объединим маску привилегий с привилегиями текущей роли nPrivileges = nPrivileges | reader.GetInt32(nIndex_RolePrivileges); aRoles.Add(new XRole(reader.GetString(nIndex_RoleName), sDescription)); } while(reader.Read()); } roles = new XRole[aRoles.Count]; aRoles.CopyTo(roles); // превратим маску привилегий в массив объектов XPrivilegeSet privilege_set = PrivilegesHelper.CreatePrivilegeSet((SystemPrivileges)nPrivileges); // создадим описание пользователя и дополним атрибуты, специфичные для нашего приложения user = new ITUser(sUserName, roles, privilege_set); user.SystemUserID = SystemUserID; user.IsUnrestricted = bIsAdmin; user.IsServiceAccount = bIsServiceAccount; user.AccessPermitted = bAccesssPermitted; if (EmployeeID != Guid.Empty) { // если пользователь - сотрудник user.EmployeeID = EmployeeID; user.LastName = sLastName; user.FirstName = sFirstName; user.EMail = sEMail; user.WorkdayDuration = nWorkingMinutesInDay; } } readUserActivityTypes(user, con); readUserManagedOrganizations(user, con); } return(user); }
/// <summary> /// Метод вызова команды ядром /// </summary> public TreeLocatorResponse Execute(EmployeeLocatorInCompanyTreeRequest request, IXExecutionContext context) { string sTreePath = ""; // путь в дереве до найденного объекта Guid foundOID = Guid.Empty; // идентификатор найденного объекта bool bMore = false; // признак того, что есть еще объекты удовлетворяющие заданному условию XStorageConnection con = context.Connection; string sQuery = @"SELECT emp.ObjectID, d.ObjectID as DepID, d.LIndex, d.RIndex, emp.Organization FROM Employee emp LEFT JOIN Department d ON emp.Department = d.ObjectID WHERE emp.LastName LIKE " + con.GetParameterName("LastName"); // если задан список игнорируемых объектов, добавим ограничение if (request.IgnoredObjects != null && request.IgnoredObjects.Length > 0) { StringBuilder bld = new StringBuilder(); bld.Append("\n\tAND NOT emp.ObjectID IN ("); foreach (Guid oid in request.IgnoredObjects) { bld.Append(con.ArrangeSqlGuid(oid)); bld.Append(", "); } bld.Length -= 2; bld.Append(")"); sQuery = sQuery + bld.ToString(); } // по умолчанию выводим (и, следовательно, ищем среди) неархивных сотрудников и сотрудников без временной нетрудоспособности. if (!request.AllowArchive) { sQuery = sQuery + " AND (emp.WorkEndDate IS NULL) AND (emp.TemporaryDisability = 0)"; } sQuery = sQuery + "\nORDER BY emp.Organization, emp.Department, emp.FirstName"; XDbCommand cmd = con.CreateCommand(sQuery); cmd.Parameters.Add("LastName", DbType.String, ParameterDirection.Input, false, request.LastName + "%"); using (IDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { foundOID = reader.GetGuid(reader.GetOrdinal("ObjectID")); Guid OrgOID = reader.GetGuid(reader.GetOrdinal("Organization")); Guid DepID; int nLIndex = -1; int nRIndex = -1; sTreePath = "Employee|" + foundOID.ToString(); if (!reader.IsDBNull(reader.GetOrdinal("DepID"))) { // если сотрудник входит в подразделение, то сформируем путь по всем подразделениям к корневому int nLIndexOrdinal = reader.GetOrdinal("LIndex"); int nRIndexOrdinal = reader.GetOrdinal("RIndex"); if (!reader.IsDBNull(nLIndexOrdinal) && !reader.IsDBNull(nRIndexOrdinal)) { nLIndex = reader.GetInt32(nLIndexOrdinal); nRIndex = reader.GetInt32(nRIndexOrdinal); } DepID = reader.GetGuid(reader.GetOrdinal("DepID")); bMore = reader.Read(); reader.Close(); if (nLIndex > -1 && nRIndex > -1) { sQuery = @"SELECT ObjectID FROM Department WHERE LIndex < @LIndex AND RIndex > @RIndex AND Organization = @OrgID ORDER BY [LRLevel] DESC"; cmd = context.Connection.CreateCommand(sQuery); cmd.Parameters.Add("LIndex", DbType.Int32, ParameterDirection.Input, false, nLIndex); cmd.Parameters.Add("RIndex", DbType.Int32, ParameterDirection.Input, false, nRIndex); cmd.Parameters.Add("OrgID", DbType.Guid, ParameterDirection.Input, false, OrgOID); sTreePath = sTreePath + "|Department|" + DepID.ToString(); using (IDataReader reader2 = cmd.ExecuteReader()) { while (reader2.Read()) { sTreePath = sTreePath + "|Department|" + reader2.GetGuid(0); } } } } else { bMore = reader.Read(); } // на корневом уровне организации sTreePath = sTreePath + "|Organization|" + OrgOID.ToString(); } } return(new TreeLocatorResponse(sTreePath, foundOID, bMore)); }
/// <summary> /// Метод запуска операции на выполнение, <входная> точка операции /// ПЕРЕГРУЖЕННЫЙ, СТРОГО ТИПИЗИРОВАННЫЙ МЕТОД /// ВЫЗЫВАЕТСЯ ЯДРОМ АВТОМАТИЧЕСКИ /// </summary> /// <param name="request">Запрос на выполнение операции</param> /// <param name="context">Контекст выполнения операции</param> /// <returns>Результат выполнения</returns> public GetEmployeesExpensesResponse Execute(GetEmployeesExpensesRequest request, IXExecutionContext context) { // Проверка / коррекция параметров if (null == request.ExceptDepartmentIDsList) { request.ExceptDepartmentIDsList = String.Empty; } // Результат операции - массив экземпляров EmployeeExpenseInfo; все // экземплряры, полученные в результате расчетов (таких итераций может // быть несколько - см. далее), будут накапливаться в общем "массиве": ArrayList arrResults = new ArrayList(); // Собственно расчет данных выполняется на уровне БД; создаем команду: using (XDbCommand cmd = context.Connection.CreateCommand()) { // ... команда - вызов хранимой процедцуры. Процедура принимает // список идентификаторов в том же виде - как строку; но ее длина, // в случае SQL, ограничена макс. размерностью. Вероятность передачи // строки с перечнем идентификаторов, общая длина которой превышает // размероность параметра, велика (скажем, для 1000 сотрудников со // средней длиной логина в 10 символов длина строки списка - уже // 10000, при том что макс. длина значения параметра - 4000). // // Поэтому весь список разбивается на части, по длине соотв. макс. // длине значения параметра. Процедура, т.о., выполняется итеративно, // пока не будет обработан весь список идентификаторов. cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "[dbo].[app_GetEmployeesExpenses]"; // Все остальные параметры при повторных вызовах не изменяются; // поэтому задаются только один раз: cmd.Parameters.Add("nIdentificationMethod", DbType.Int32, ParameterDirection.Input, false, (int)request.IdentificationMethod); cmd.Parameters.Add("sExceptedDepIDs", DbType.String, ParameterDirection.Input, false, request.ExceptDepartmentIDsList); cmd.Parameters.Add("dtPeriodBeginDate", DbType.Date, ParameterDirection.Input, false, request.PeriodBegin); cmd.Parameters.Add("dtPeriodEndDate", DbType.Date, ParameterDirection.Input, false, request.PeriodEnd); // ... пустая строка - недопустимый параметр; здесь задается для // того, чтоб сразу добавить параетр в коллекцию: cmd.Parameters.Add("sEmployeesIDs", DbType.String, ParameterDirection.Input, false, String.Empty); // Далее - итерации по "частям" списка; до тех пор, пока не будет обработан весь список: string sSrcEmpIDsList = request.EmployeesIDsList; for (int nCurrPos = 0; nCurrPos < sSrcEmpIDsList.Length;) { // Выделение "части" списка: string sCurrIDsListPart; if (sSrcEmpIDsList.Length - nCurrPos < DEF_EmployeesIDsList_MaxLength) { sCurrIDsListPart = (0 == nCurrPos ? sSrcEmpIDsList : sSrcEmpIDsList.Substring(nCurrPos)); nCurrPos += sCurrIDsListPart.Length; } else { int nNextPartPos = sSrcEmpIDsList.LastIndexOf(",", nCurrPos + DEF_EmployeesIDsList_MaxLength, DEF_EmployeesIDsList_MaxLength - 1); if (-1 == nNextPartPos) { throw new ArgumentException( String.Format( "Список идентификаторов включает идентификатор, длина которого недопустима (более {0})", DEF_EmployeesIDsList_MaxLength), "[request].EmployeesIDsList"); } sCurrIDsListPart = sSrcEmpIDsList.Substring(nCurrPos, nNextPartPos - nCurrPos); nCurrPos = nNextPartPos + 1; } // Выделенная "часть" задается как значение параметра: cmd.Parameters["sEmployeesIDs"].Value = sCurrIDsListPart; using (IDataReader reader = cmd.ExecuteReader()) { if (0 != reader.FieldCount) { if (reader.FieldCount < 4) { throw new ApplicationException("Некорректные данные расчета (SQL): недостататочное количество колонок в результирующем наборе (" + reader.FieldCount + ")"); } // Результат выполнения процедуры - рекордсет, каждая строка // которого содержит идентификатор сотрудника, требуемое время для // списания и реальное списанное время: int nOrd_EmployeeID = reader.GetOrdinal("EmployeeID"); int nOrd_RateExpenses = reader.GetOrdinal("RateExpenses"); int nOrd_RealExpenses = reader.GetOrdinal("RealExpenses"); while (reader.Read()) { EmployeeExpenseInfo info = new EmployeeExpenseInfo(); info.EmployeeID = reader.GetString(nOrd_EmployeeID); info.RateExpense = reader.GetInt32(nOrd_RateExpenses); info.RealExpense = reader.GetInt32(nOrd_RealExpenses); arrResults.Add(info); } } } } } // Итоговый результат операции: GetEmployeesExpensesResponse response = new GetEmployeesExpensesResponse(); response.PeriodBegin = request.PeriodBegin; response.PeriodEnd = request.PeriodEnd; response.Expenses = new EmployeeExpenseInfo[arrResults.Count]; if (arrResults.Count > 0) { arrResults.CopyTo(0, response.Expenses, 0, arrResults.Count); } return(response); }
public XResponse Execute(SaveObjectInternalRequest request, IXExecutionContext context) { ITUser user = (ITUser)XSecurityManager.Instance.GetCurrentUser(); ArrayList aObjects = request.DataSet.GetModifiedObjectsByType("TimeLoss", true); foreach (DomainObjectData xobj in aObjects) { if (!xobj.HasUpdatedProp("Worker") && xobj.IsNew) { xobj.SetUpdatedPropValue("Worker", user.EmployeeID); } // получим папку, проверим у папки отсутствие флага IsLocked object vValue = xobj.GetPropValue("Folder", DomainObjectDataSetWalkingStrategies.UseUpdatedPropsThanLoadedProps); DomainObjectData xobjFolder = null; if (vValue is Guid) { xobjFolder = xobj.Context.Get(context.Connection, xobj, "Folder", DomainObjectDataSetWalkingStrategies.UseUpdatedPropsThanLoadedProps, true); // проверим состояние папки. если она закрыта или в ожидании закрытия, то запретим списание if ((FolderStates)xobjFolder.GetLoadedPropValue("State") == FolderStates.Closed || (FolderStates)xobjFolder.GetLoadedPropValue("State") == FolderStates.WaitingToClose || (FolderStates)xobjFolder.GetLoadedPropValue("State") == FolderStates.Frozen) { throw new XSecurityException("Списания в папку в состоянии \"Закрыто\" или \"Ожидание закрытия\" запрещены. По вопросам списаний обращайтесь к менеджеру."); } // проверим наличие у папки специального аттрибута, запрещающего списание if ((bool)xobjFolder.GetPropValue("IsLocked", DomainObjectDataSetWalkingStrategies.UseUpdatedPropsThanLoadedProps)) { throw new XSecurityException("<b>Списания в данную папку запрещены.</b><br/>По вопросам списаний обращайтесь к менеджеру."); } FolderPrivilegeManager manager = (XSecurityManager.Instance.SecurityProvider as SecurityProvider).FolderPrivilegeManager; // у пользователя должны быть права на списание в данной папке if (!manager.HasFolderPrivilege(user, FolderPrivileges.SpentTimeByProject, xobjFolder, context.Connection)) { throw new XSecurityException("<b>Пользователь должен обладать в проекте привилегией \"Списание времение на проект\".</b><br/>По вопросам списаний обращайтесь к менеджеру."); } // если у пользователя нет привилегии «Разрешение списания на папку с неоднозначным определением направления» // проверим - является ли данная папка папкой с неоднозначным определением направления if (!manager.HasFolderPrivilege(user, FolderPrivileges.TimeLossOnUnspecifiedDirection, xobjFolder, context.Connection)) { using (XDbCommand c = context.Connection.CreateCommand()) { c.CommandType = CommandType.Text; c.CommandText = @" IF ( SELECT t.AccountRelated FROM dbo.ActivityType t WITH(NOLOCK) JOIN dbo.Folder fT WITH(NOLOCK) ON fT.ActivityType = t.ObjectID WHERE fT.ObjectID = @FolderID ) = 0 SELECT 1 ELSE SELECT TOP 1 t.DirsQnt FROM ( SELECT fU.ObjectID, fU.LRLevel, ( SELECT COUNT(*) FROM dbo.FolderDirection fd WITH(NOLOCK) WHERE fd.Folder = fU.ObjectID ) AS DirsQnt FROM dbo.Folder fT WITH(NOLOCK) JOIN dbo.Folder fU WITH(NOLOCK) ON fU.Customer = fT.Customer AND fU.LIndex <= fT.LIndex AND fU.RIndex >= fT.RIndex WHERE fT.ObjectID = @FolderID ) t WHERE DirsQnt > 0 ORDER BY LRLevel DESC "; c.Parameters.Add("FolderID", DbType.Guid, ParameterDirection.Input, false, vValue); object oResult = c.ExecuteScalar(); string sReport = null; if (null == oResult || DBNull.Value == oResult) { sReport = "для которой не определено ни одного направления"; } else if (1 != (int)oResult) { sReport = "для которой определено более одного направления"; } if (null != sReport) { throw new XSecurityException( "<b>Списания в данную папку запрещены.</b><br/>" + "У Вас нет прав списывать в папку, " + sReport + ". " + "По вопросам списаний <b>обращайтесь к менеджеру</b>."); } } } } // если в объекте заданы "виртуальные" свойства if (xobj.HasUpdatedProp("LossFixedStart") && xobj.GetUpdatedPropValue("LossFixedStart") is DateTime && xobj.HasUpdatedProp("LossFixedEnd") && xobj.GetUpdatedPropValue("LossFixedEnd") is DateTime) { if (!xobj.IsNew) { throw new ApplicationException("Задание диапазона допустимо только при создании объекта \"Списание времени\""); } // получим даты начала и окончания периода DateTime dtPeriodStart = (DateTime)xobj.GetUpdatedPropValue("LossFixedStart"); DateTime dtPeriodEnd = (DateTime)xobj.GetUpdatedPropValue("LossFixedEnd"); if (dtPeriodStart > dtPeriodEnd) { DateTime dtTemp = dtPeriodEnd; dtPeriodEnd = dtPeriodStart; dtPeriodStart = dtTemp; } Guid employeeID = (Guid)xobj.GetUpdatedPropValue("Worker"); // проверим, что в данном периоде отсутствуют списания XDbCommand cmd = context.Connection.CreateCommand(""); cmd.CommandText = @"SELECT DISTINCT CONVERT(varchar, x.SpentDate, 104) FROM ( SELECT ts.RegDate AS SpentDate FROM TimeSpent ts JOIN Task t ON ts.Task = t.ObjectID WHERE t.Worker = @EmployeeID AND ts.RegDate >= @dtPeriodStart AND ts.RegDate < @dtPeriodEnd UNION SELECT ts.LossFixed AS SpentDate FROM TimeLoss ts WHERE ts.Worker = @EmployeeID AND ts.LossFixed >= @dtPeriodStart AND ts.LossFixed < @dtPeriodEnd ) x" ; cmd.Parameters.Add("EmployeeID", DbType.Guid, ParameterDirection.Input, false, employeeID); cmd.Parameters.Add("dtPeriodStart", DbType.Date, ParameterDirection.Input, false, dtPeriodStart); // AddDays(1) - т.к. в условии запроса знак "меньше" cmd.Parameters.Add("dtPeriodEnd", DbType.Date, ParameterDirection.Input, false, dtPeriodEnd.AddDays(1)); using (IDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { StringBuilder bld = new StringBuilder(); do { if (bld.Length > 0) { bld.Append(", "); } bld.Append(reader.GetString(0)); } while(reader.Read()); throw new XBusinessLogicException( String.Format("У вас уже имеются списания на следующие даты в заданном периоде ({0},{1}): {2}", dtPeriodStart.ToShortDateString(), dtPeriodEnd.ToShortDateString(), bld.ToString()) ); } } // Получаем "набор пар" дата - норма сотрудника на дату Dictionary <DateTime, int> dictDateRates = new Dictionary <DateTime, int>(); dictDateRates = GetDayRates(context.Connection, dtPeriodStart, dtPeriodEnd, employeeID); // пойдем по всем дням периода (dtPeriodEnd, dtPeriodStart) // и для каждой даты создадим новый объект Списание времени с количеством времени равном рабочему дню // При этом, будем игнорировать даты, попадающие на выходные/праздники TimeSpan period = (dtPeriodEnd - dtPeriodStart); for (int nOffSet = 0; nOffSet <= period.TotalDays; ++nOffSet) { int nRate = 0; DateTime dtDate = dtPeriodStart.AddDays(nOffSet); // Если удалось получить норму сотрудника на соотв. дату, то создадим объект if (dictDateRates.TryGetValue(dtDate, out nRate)) { // Если полученная норма больше 0, тогда создадим списание if (nRate > 0) { DomainObjectData xobjNew = createTimeLossObject(request.DataSet, xobj, user); xobjNew.SetUpdatedPropValue("LossFixed", dtDate); // списание длиной в количество минут в рабочем дне xobjNew.SetUpdatedPropValue("LostTime", nRate); } } } // исходный объект надо удалить request.DataSet.Remove(xobj); } } XSecurityManager sec_man = XSecurityManager.Instance; IEnumerator enumerator = request.DataSet.GetModifiedObjectsEnumerator(false); DomainObjectData xobject; while (enumerator.MoveNext()) { xobject = (DomainObjectData)enumerator.Current; if (xobject.ToDelete) { sec_man.DemandDeleteObjectPrivilege(xobject); } else { sec_man.DemandSaveObjectPrivilege(xobject); } } // #1: Запись данных XStorageGateway.Save(context, request.DataSet, request.TransactionID); // Специального результата операция не возвращает return(new XResponse()); }