Run User Compare with ERPConnect (Theobald) - c#

I would like to know if anyone knows if it is possible to run a SAP User Compare from c# using ERPConnect 4 from Theobald? If so, how?
I can open a connection to SAP and run functions - just don't know how to do User Compare.
EDIT:
It seems like we have to run the report PFCG_TIME_DEPENDENCY.
If anyone knows how to run a report with ERPConnect, or if there exists a functional module in SAP that can run a report, that will also help.

I am not exactly sure what your comparison has to include, but I assume, that you want to compare attributes of the users. If that is the case, you could download the users data from the SAP tables. Here is a starting point for what tables you probably need: http://www.tcodesearch.com/sap-tables/detail?id=USR01
USER01 is the user master record, containing all user with it's main attributes. You can find other interesting related user table through the link above.
To read a table using Erpconnect, look at this link: https://my.theobald-software.com/index.php?/Knowledgebase/Article/View/21/23/reading-sap-tables-directly
You need to create an instance of the ReadTable class. Then you add the fields you are interested in using the AddField method (e.g. MANDT and BNAME for the USR01 table). You could but don't have to enter filter criteria using the AddCriteria method. If you do add multiple creteria, be sure to add boolean operators like "and" or "or":
table.AddCriteria("LANGU = 'D'");
table.AddCriteria("AND MANDT = '007'");
Finally set the table name of the table you want to download and execute the Run-Method. After that you can loop through the results stored in <your RunTable-Instance>.Result.Rows
Sascha

Related

C# check if SQL query is only for creating view

I would like to add an option that user using web ui can define some views in our product.
We let super admins put in SQL query that would create that view.
Do you know if there are any tools for parsing SQL Query and check if it is valid SQL Query for only creating view?
I assume the input is secure, so your superusers are not going to try to inject stuff ;-)
Anyway the comment above is correct, at least you should check for semicolon and comments. Also that the string starts with "SELECT "
The easiest way - after this basic checks - would be to let them insert the SELECT-Query alone and test it on your connections. Then catch any exception and display it to the superuser.
In case of success, you could even display some of the result, in order give them the possibility to validate the query.
After that you prefix in your code the SELECT with "CREATE VIEW AS " in order to create the view on your database.
One possibility is to create a unique role that has select access on every table in the database but nothing else. Then have your C# run the query as that user in a try/catch block. This would even eliminate the possibility of SQL injection and/or provide a failsafe for well meaning but careless users.
The main disadvantage I see is that you would need to continually update permissions to ensure that the user is granted select access to new objects, but I think you can define those types of cascading permissions at the schema level... never tried it at the database level.
Force the query to begin with “CREATE VIEW”, e.g. by prefixing whatever is entered with that string.
Make sure that there is no semicolon inside the query. This will exclude some valid queries (that contain something like “WHERE a = ';'” or “/* comment; */”), but it is simple and you might get away with it.

SQL Server prevent only specific table from updating based on parameter passed from C# controller

In our .net application, we have a tool that allows you to type SQL in a browser and submit it, for testing. In this context, though, I need to be able to prevent testers from writing to specific tables. So, based on the parameter passed from the controller (InSupportTool = true, or something), I need to know if SQL Server is allowed to make updates or inserts to, say, an accounts table.
Things I've tried so far:
I have tried looking into triggers, but there is no before trigger available, and I've heard people don't recommend using them if you can help it.
Parsing the passed SQL string to look for references to inserting or updating on that table. This is even more fragile and has countless ways, I'm sure, of getting around it if someone wanted to.
Check constraint, which is the closest I feel I've gotten but I can't quite put it together.
For check constraints, I have this:
ALTER TABLE Accounts WITH NOCHECK
ADD CONSTRAINT chk_read_only_accounts CHECK(*somehow this needs to be dynamic based on parameters passed from C# controller*)
The above works to prevent updates to that table, but only if I put a check like 1 = 0. I've seen a post where people said you could use a function as the check, and pass parameters that way, but I'm at the limit of my familiarity with SQL/.net.
Given what I'm looking to do, does anyone have experience with something like this? Thanks!
Since the application is running under a different account than the end user, you could specify your application name in the connection string (e.g. Application Name=SupportTool) and check that in an after trigger, rolling back the transaction as needed:
CREATE TABLE dbo.example(
col1 int
);
GO
CREATE TRIGGER tr_example
ON dbo.example
AFTER INSERT, UPDATE, DELETE
AS
IF APP_NAME() = N'SupportTool'
BEGIN
ROLLBACK;
THROW 50000, 'This update is not allowed using the support tool', 1;
END;
GO
INSERT INTO dbo.example VALUES(1);
GO

2 errors when trying to use RFCDestination.Repository.GetTableMetadata(string tablename)

I know that you can get the data of a table in a SAP Server with the function RFCDestination.Repository.GetTableMetadata(string tablename). Unfortunately I get an error when I try to execute the command. The weird thing is when I give a exisiting table I get a different error when I try something random as a tablename.
Existing table:
var x = dest.Repository.GetTableMetadata("TFTIT");
Error:
SAP.Middleware.Connector.RfcInvalidStateException: "cannot find TABLE specified by TFTIT"
Random tablename:
var x = dest.Repository.GetTableMetadata("Test123");
Error:
SAP.Middleware.Connector.RfcInvalidStateException: "metadata for TableOnly TEST123 not available: NOT_FOUND: No active nametab exists for TEST123"
I know there is a way to get the data of a table with the help of a function module but I need to use the GetTableMetadata function.
One cannot do so much wrong when calling RfcRepository.GetTableMetadata(string). Does your used user ID has the required RFC authorizations for repository queries as listed in SAP note 460089 (scenario 3)? If yes, this is maybe a bug in the NCo3 library or even in the ABAP backend. Do you use NCo's latest patch level? This is currently NCo 3.0.20.
If not, try updating the library first.
Otherwise I recommend to create an SAP support ticket for the first error message. The second error is normal when the specified table name does not exist.
Alternatively you may also try what happens if calling RfcRepository.GetStructureMetadata(string) for this table instead. The meta data for tables and structures is quite similar and the same remote function modules are used for the DDIC queries. Maybe this works. However, I think in the first place RfcRepository.GetTableMetadata(string) should work here.
I hope this helps.

Saving SSRS multi select parameter value with wildcard

I have searched and searched and have not been able to find the answer to this. I'm no stranger to SSRS, .Net (c# and vb.net), SQL, etc...been in it for years. I currently have a multi-select report parameter that is populated by a dataset in my report. There are hundreds of entries, so I built it to be driven by a wildcard character in a preceding parameter. Everything works fine right now. My question is this: is it possible to enter a wildcard value, select one (or more) of the filtered values and then store that/those value(s) on selection so that a user can go back and enter another wildcard value and select from a newly filtered list? (Basically, remember what has been selected in the overall dataset before report execution and create some sort of comma-separated list as the final parameter value to be passed to the report) I realize this may be better served in a web app w/a reportviewer control, but I'm trying to avoid deviating from the native SSRS server if possible. Thanks in advance!
The way I might approach this (not actually done it but the theory sounds ok)
Have 2 parameters for user input, your current one and a hidden one called say #filter (visible) and #filterHistory (this is the hidden one)
Have a textbox (formatted like button) with something like "Refine" as the text. Set the action to call your report again but set the #filterHistory to be something like #filterHistory & ", " & #filter. Basically we keep appending the last user input to the history.
Then your report would filter based on both parameters. You'll have to do some parsing of the delimited parameter now to split it out into the constituent parts but you get the idea.
I've no time to build a test report but hopefully that will point you in the right direction. If it doesn't help or work then comment and I'll see if I can knock up a quick example.

Using logical OR with Crystal Reports parameter

I am working on a Crystal Reports in Visual Studio 2010 and I have a variety of different parameters and prompts for the user to filter out the specific data they want. For example, I have a parameter for Account and a parameter for Product Name dynamically populated. By default, if a user selects a filter for each of these parameters (account A and product B for example) a logical AND is performed. Only rows containing account A and product B are returned.
Is there a way to make this behave as an OR or an AND (user specifies?) So I can return all rows for account A OR product B
I know that it would be easy to change my formulas to treat this as an OR but what I would really like is for the user to be able to somehow specify whether or not the parameter should be treated as an AND or an OR.
If I'm understanding you correctly, you can pass a third string parameter in, call it {?Logic}, which contains either "AND" or "OR", and from there you can do:
IF {?Logic} = "AND"
' Do your AND code here
ELSE
' Do your OR code here
I realize you're basically repeating the query, once using AND and once using OR, but as long as the query isn't too cumbersome, this might be the cleanest way to do it.

Categories

Resources