LINQ: executing stored procedure, but skipping cursor within - linq

I'm working on this wonky data project (C#/LINQ/MS SQL). I receive a very poorly formatted dataset and I'm working at building up some meaningful reports with the data. For one of the reports ("SwitchFlow"), I'm created a Stored Proc called "SwitchFlowGenerate". It takes two params, the date of the report and the company of origin.
At the very end of the stored proc I ended up using a cursor (uck) to loop through the data to generate a customer count field value.
When I run the stored proc within management studio it works 100%. When I had the stored proc to my LINQ-to-SQL and call it from a Visual Studio C# console app, it doesn't completely work...
From my app, the stored proc "SwitchFlowGenerate" populates the report table as it should, returns no error codes (in debug or production), but it appears to not execute the cursor portion of the stored proc (leaving the customer count field at zero).
I call the stored proc from MS SQL Management Studio simply like this:
exec switchflowgenerate '03-13-2012', 'ace'
From C#/LINQ I call it like this:
db.SwitchFlowGenerate(DateTime.Now, ldc);
(note: .Now is the same as above in MSMS)
The cursor portion of the code looks like this:
**--Update Customer Count column to reflect account switch movement
DECLARE #Adjust INT
SET #Adjust = 0
DECLARE #cc nvarchar(100)
DECLARE #stat nvarchar(100)
DECLARE SFC CURSOR FOR SELECT CustomerCount, [Status] FROM SwitchFlow WHERE ReportDate = #rptDate AND LDC = #ldc FOR UPDATE
OPEN SFC
FETCH SFC INTO #cc, #stat
WHILE (##FETCH_STATUS = 0)
BEGIN
IF #stat = 'Dropped' BEGIN SET #Adjust = -1 END
IF #stat = 'Start' BEGIN SET #Adjust = 1 END
IF #stat = 'In Queue - To Start' BEGIN SET #Adjust = 1 END
IF #stat = 'In Queue - To Drop' BEGIN SET #Adjust = -1 END
IF #stat = 'Reenrolling' BEGIN SET #Adjust = 1 END
IF #stat = '#### SAME DAY ####' BEGIN SET #Adjust = 0 END
SET ##StartingTotal = ##StartingTotal + #Adjust
UPDATE [SwitchFlow] SET CustomerCount = ##StartingTotal WHERE CURRENT OF SFC
FETCH SFC INTO #cc, #stat
END
CLOSE SFC
DEALLOCATE SFC**
Linq generates:
Generating Data For: ACE on 3/13/2012
EXEC #RETURN_VALUE = [dbo].[SwitchFlowGenerate] #rptDate = #p0, #ldc = #p1
-- #p0: Input DateTime (Size = -1; Prec = 0; Scale = 0) [3/13/2012 9:56:59 AM]
-- #p1: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [ACE]
-- #RETURN_VALUE: Output Int (Size = -1; Prec = 0; Scale = 0) [Null]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
Any help or insight would be greatly appreciated ~especially if someone has an idea of how to accomplish that without a cursor.
Thanks!!
TK

Related

What's the fastest way to list all the exe files in a huge directory in Delphi?

At the moment I'm doing something like this:
var
Files: TArray<String>;
if IncludeSubDirs then
Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soAllDirectories)
else
Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soTopDirectoryOnly);
Path is a user defined String that can point to any existing directory. For "big" directories with a ton of files and with IncludeSubDirs = True (C:\Windows\ for example) GetFiles takes a very long time (like 30+ secs).
What would be the fastest way to list all the exe files in a "big" directory under Windows with Delphi (if any)?
I did some benchmarking and for a huge directory FindFirst / FindNext is about 1.5 to 3% faster than using TDirectory. I would say than both are equivalent in speed (for my use case I saved about 1 sec per minute). I ended up using FindFirst / FindNext since you get results progressively and not all at once, memory management seemed better and it's easier to cancel midway. I also used a TThread to avoid blocking my UI.
This is what I ended up with:
procedure TDirectoryWorkerThread.AddToTarget(const Item: String);
begin
if (not Self.Parameters.DistinctResults) or (Self.Target.IndexOf(Item) = -1) then
Self.Target.Add(Item);
end;
procedure TDirectoryWorkerThread.ListFilesDir(Directory: String);
var
SearchResult: TSearchRec;
begin
Directory := IncludeTrailingPathDelimiter(Directory);
if FindFirst(Directory + '*', faAnyFile, SearchResult) = 0 then
begin
try
repeat
if (SearchResult.Attr and faDirectory) = 0 then
begin
if (Self.Parameters.AllowedExtensions = nil) or (Self.Parameters.AllowedExtensions.IndexOf(ExtractFileExt(SearchResult.Name)) <> -1) then
AddToTarget(Directory + SearchResult.Name);
end
else if Self.Parameters.IncludeSubDirs and (SearchResult.Name <> '.') and (SearchResult.Name <> '..') then
ListFilesDir(Directory + SearchResult.Name);
until Self.Terminated or (FindNext(SearchResult) <> 0);
finally
FindClose(SearchResult);
end;
end;
end;

Oracle DBMS_DEBUG.GET_VALUE can't get variable values when debugging large packages

I try to debug some function in PL\SQL. When I debug large package (package body contains 21666 lines of code), I can't see variable values, I always get (Not a variable).
I added debug information.
When debuging smaller packages this problem don't ocures.
This is part of PL\SQL Developer debug log:
begin
handle.owner := :package_owner;
handle.name := :package_name;
if :inbody = 1 then
handle.namespace := sys.dbms_debug.namespace_pkg_body;
else
handle.namespace := sys.dbms_debug.namespace_pkgspec_or_toplevel;
end if;
:result := sys.dbms_debug.get_value(variable_name => :variable_name,
handle => handle,
scalar_value => :scalar_value,
format => :format);
if :result = 16 then :result := 3; end if;
end;
:RESULT = 3
:VARIABLE_NAME = requisition_no_
:SCALAR_VALUE = Null
:FORMAT = Null
:PACKAGE_OWNER = USER
:PACKAGE_NAME = PURCHASE_API
:INBODY = 1
error_no_such_object CONSTANT binary_integer := 3; -- no such var/parm
error_bad_handle CONSTANT binary_integer := 16; -- can't set bpt there
Anyone knows how to fix that ?
Maybe there is some Oracle Server configuration telling how large package body can be to have variable values on stack.

How to lock user account after multiple attempted and password must not be plain text in Oracle Apex?

I got a user table with column email, password, is_locked(varchar2(1) default = 'N'), login_failed(number default = 0). Below is the code which I write for my custom authentication scheme:
FUNCTION my_user_auth(
p_username in varchar2,
p_password in varchar2)
RETURN boolean
IS
l_result NUMBER := 0;
l_locked VARCHAR2(1) := 'N';
Sts NUMBER := 0;
v_return BOOLEAN := FALSE;
BEGIN
SELECT 1, USER_TYPE_ID, IS_LOCKED INTO l_result, Sts, l_locked
FROM USER_INFO
WHERE LOWER(EMAIL) = LOWER(p_username)
AND LOGIN_PASSWORD = p_password;
if (l_locked ='N' AND l_result = 1) then
APEX_UTIL.SET_SESSION_STATE('GLOBAL_STATUS_ITEM', Sts);
v_return := TRUE;
elsif (l_locked ='Y') then
apex_util.set_custom_auth_status (p_status => 'Account Locked, Exceeded Maximum Attempts! Please contact support staff.');
v_return := false;
end if;
RETURN v_return;
END my_user_auth;
Is that possible to make the user's email locked (change "is_locked" value to 'Y') after several failed attempt on login?
I had tried to add the code below but after added the code the user can't even login to the system even the password is correct:
if(l_result = 0) then
if(login_failed > 3) then
UPDATE USER_INFO
SET is_locked = 'Y'
WHERE email = p_username;
elsif
UPDATE USER_INFO
SET login_failed = login_failed + 1
WHERE email = p_username;
endif;
endif;
In addition, I got a form based on table which allow user to update their password, how can I set a constraint to make sure that the password insert is not plain text, e.g. included uppercase, special character and etc.
Thank you.
You can achieve this using JavaScript/Oracle Function. If you prefer to use JavaScript, i hope the below script helps you to achieve it assuming P1_PASSWORD is the variable the gets the input,add the below script on change (dynamic action).
var hasUpperCase = /[A-Z]/.test($v("P1_PASSWORD"));
var hasLowerCase = /[a-z]/.test($v("P1_PASSWORD"));
var hasNumbers = /\d/.test($v("P1_PASSWORD"));
var hasNonalphas = /\W/.test($v("P1_PASSWORD"));
if (hasUpperCase + hasLowerCase + hasNumbers + hasNonalphas < 3 || $v("P1_PASSWORD").length < 8 )
{
apex.message.clearErrors();
apex.message.showErrors([
{
type: apex.message.TYPE.ERROR,
location: ["inline"],
pageItem: "P1_PASSWORD",
message: "Password should contain Uppercase,lowercase,number and Special character greater than 8 characters",
unsafe: false
}
]);
}
For Oracle Function, you can refer to the Oracle Function available in the $ORACLE_HOME/rdbms/admin/utlpwdmg.sql location. Modify the function and create it as per your needs and you can use it for validation.
Hope this helps you.

Can't exit a while loop

I can't get readln to change the condition
program CFS;
{Defining Constants}
const
{Pay Rates}
ManagerBasic = 8000;
AssistManagerBasic = 7000;
SupervisorBasic = 5000;
SalesStaffBasic = 3000;
{Allowances}
DailyAllowance = 0.11;
TravelAllowance = 0.06;
EntertainmentAllowance = 0.035;
CommissionRate = 0.03;
{Deductions}
SocialSecurity = 0.06;
EnvironmentLevy = 0.01;
Insurance = 0.02;
{creating and initialising variables where necessary}
var
Name : string;
//i : integer = 0;
StaffType : string;
TotalSales : real = 0.0;
CommissionEarned : real = 0.0;
MajorLoop : integer = 1;
begin
{this is just the psueudocode comments for the real program}
writeln('The Caribbean Fashion Store');
writeln('Electronic Communication Calculator Version 1.0.1');
writeln('Build No. 001');
writeln('Sands, Sheba');
{We will use a while loop as a means of making the program start and stop at the user s will. First we ask for a choice:'}
writeln();
writeln('To process an employee, type 1 and press Enter, otherwise type 0 and press Enter');
while (MajorLoop = 0) do
begin
writeln('To process another employee, type 1 and press Enter, otherwise type 0 and press Enter');
end;
writeln(ManagerBasic/DailyAllowance);
{read is placed to stop the program}
readln();
end.
In the var section you initialize MajorLoop with the value 1 so the loop will never run.
Change your while to something like
while(MajorLoop = 1) do
begin
writeln('To process another employee, type 1 and press Enter, otherwise type 0 and press Enter');
readln(MajorLoop);
end;
This way if the user type 0 the loop ends (I'm assuming that's what you want to do).

Email output node

CREATE COMPUTE MODULE TestFlow_Compute1
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyMessageHeaders();
--CALL CopyEntireMessage();
SET OutputRoot.EmailOutputHeader.To = 'abcd123#gmail.com';
SET OutputRoot.EmailOutputHeader.From = 'xyz456#gmail.com';
SET OutputLocalEnvironment.Destination.Email.SMTPServer ='smtpout.secureserver.net:25';
DECLARE sid INTEGER InputRoot.XMLNSC.emp.eid;
DECLARE track CHARACTER InputRoot.XMLNSC.emp.etid;
DECLARE sname CHARACTER InputRoot.XMLNSC.emp.ename;
DECLARE sorg CHARACTER InputRoot.XMLNSC.emp.eorg;
DECLARE ssal INTEGER InputRoot.XMLNSC.emp.esal;
SET OutputRoot.XMLNSC.Data.Result.cty=PASSTHRU('SELECT city from ITGDB.mssusr14.collector where targetid='||track TO Database.mss);
SET OutputRoot.XMLNSC.Data.Result.id1=sid;
SET OutputRoot.XMLNSC.Data.Result.nme=sname;
SET OutputRoot.XMLNSC.Data.Result.or=sorg;
SET OutputRoot.XMLNSC.Data.Result.sl=ssal;
RETURN TRUE;
END;
CREATE PROCEDURE CopyMessageHeaders() BEGIN
DECLARE I INTEGER 1;
DECLARE J INTEGER;
SET J = CARDINALITY(InputRoot.*[]);
WHILE I < J DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I = I + 1;
END WHILE;
END;
CREATE PROCEDURE CopyEntireMessage() BEGIN
SET OutputRoot = InputRoot;
END;
END MODULE;
I used above esql code to send data to email output node, but it is not propagating.Could you please suggest me what is the mistake in the code?
I don't see a PROPAGATE call.
PROPAGATE TO TERMINAL 'out' DELETE NONE;
For Example. Hopefully this helps get you moving. I've also had to RETURN FALSE; rather than TRUE to prevent an additional message over the terminal.

Resources