Code Analysis with SonarQube and C#


Sometimes, and especially when our application is huge or there are a lot of people working on it, maybe is usefull take a global vision of the state of the source code, view the possible improvements, avoid possible future issues or be aligned with the design guidelines.

There are a lot of programs to manage this, even Visual Studio has his own Code Analysis (in my opinion is very poor). For me, one of the best is SonarQube, that have a web interface and is easy to track, view, get reports, etc. In this post we will configure and run SonarQube with C# for our project.

 

The first step is download SonarQube from his page (http://www.sonarqube.org/downloads/). We unzip the files in a folder. We need to take into account that SonarQube not needs install it, the files that it needs for run are these files unzipped.

1

 

The next step is go to this folders and find our distribution inside bin folder, in my case “windows-x86-32“, and execute StartSonar.bat to configure apache and SonarQube. Probably you can get an  error if you don’t have JRE installed. You can download it from here. After that you can navigate to http://localhost:9000 to display the home page of SonarQube.

2

You can change some parameters from a config file inside installation folder (conf/sonar.properties) to manage the port, connection pool, proxy, etc., but we can use the default parameters). Ok, now we need to install the plugin for run C# or VB.Net projects. We make login in the application (admin/admin) and we go to Update Center menu (on the left). Here we can see the installed o available plugins.

3

We install the C# and .Net plugins. After that we need to restart the SonarQube (we need to close and launch again StartSonar.bat). We are finishing our configuration, we only need the last step, get a runner, in this case we will use Sonar-Runner (we can use others). We can download it from here. As SonarQube it no need to install it, is enough with download the files. Now we have all ready to work. To avoid go to the folders each time, we can register the path in “Windows path” to recognize the program names (Computer/Properties/Advanced system settings/Environment Variables). We search the Path variable and is needed to add the folder that contains StartSonar and the runner (D:\sonarqube\sonar-runner-2.3\bin\;D:\sonarqube\bin\windows-x86-32\; in my case). With that we can start SonarQube or Runner only typing StartSonar or sonnar-runner in a cmd window.

We need to go to our solution project and create a file called sonar-project.properties. In this file we need to configure the project Name, path and the language. We need to place this file in the same place that the solution. This is the common content of the file:

sonar.projectKey=KeyOfTheProject
sonar.projectName=NameOfTheProject
sonar.projectVersion=1.0

sonar.sources=.
sonar.language=cs
sonar.sourceEncoding=UTF8

It’s time to analyze our project. We need to open a cmd screen and go to our solution folder. After navigate to the folder we type “sonar-runner” and the analysis starts. If you have an error about FxCop, you need to go to the SonarQube Portal, go to General Settings and in .Net FxCop we need specify the path of FxCop.

6

 

Run again the sonar-runner and this time should be work. When the analisys ends, we can see in SonarQube portal a new link on the left with our project and the results:

7

 

You can detail each kind of issue, see graphics, summary, evolution, etc. The ideal is don’t have any Evidence or the less possible.

8

 

Call server methods with JavaScript events


Sometimes, will be usefull call some server methods after detect an event. For example, click on a button, select a value in dropdownlist.
With the framework controls we can do this kind of actions (default events implemented), but what happen if we  want control other events like “type a value”, “make double click”, etc.
To manage this events we need to manage trough javascript and if we want to invoke a server method, one solution should be call WebMethod through ajax (http://api.jquery.com/jquery.ajax/).
Exists an easy way to do that without jquery ajax. We can associate a javascript event with a server method.
To do that we need to register the event in the Page_Init method and assign them to the control. We register the control and his events.
var onBlurScript = Page.ClientScript.GetPostBackEventReference(TxtJsEvntBox, "OnDblClick");
TxtJsEvntBox.Attributes.Add("ondblclick", onBlurScript);

var onKEyPress = Page.ClientScript.GetPostBackEventReference(TxtJsEvntBox, "OnKeyUp");
TxtJsEvntBox.Attributes.Add("onkeyup", onKEyPress);
The next step is manage the control and the event that has been triggered in Page_Load.
var ctrlName = Request.Params[Page.postEventSourceID];
var args = Request.Params[Page.postEventArgumentID];
HandleCustomPostbackEvent(ctrlName, args);
After that we need to design the logic of the server method for each event previously defined, for example like this:
if (ctrlName == TxtJsEvntBox.UniqueID) {
  switch (args) {
    case "OnDblClick":
      LblTest.Text = "On Double Click Event at " + DateTime.Now; break;
    case "OnKeyUp":
      LblTest.Text = "On Key Up Event at " + DateTime.Now;
      ScriptManager.RegisterStartupScript(this, GetType(), "focus", GetFocus(ctrlName.Replace('$', '_')), true);
      break;
  }
}
Maybe this is more easy to understand and implement if you not are familiarized with javascript or jquery language. You can download the full example here.

Get Inserted or Updated rows with Merge in Oracle


Sometimes when we need to insert values in a table from a select, some of the rows can exists or not in the new table. In this case maybe we need to update or insert in the table. The sentence merge help us to do that:

MERGE <hint> INTO <table_name>
USING <table_view_or_query>
ON (<condition>)
WHEN MATCHED THEN <update_clause>
DELETE <where_clause>
WHEN NOT MATCHED THEN <insert_clause>
[LOG ERRORS <log_errors_clause> <reject limit <integer | unlimited>];

You can see the entire documentation in the oracle docs here.

 

Unfortunatelly one of the biggest inconvenients of merge is that we don’t know which registers are been inserted and which are been updated. In Sql Server we have the “OUTPUT” clause to retrieve these values but in Oracle this clause does’t exists. So we will try to make something similar to this behaviour. Reviewing the idea posted by Adrian Billington in his article, I have created an improvement to be able to know which values are been updated or inserted, how many, etc.

We will have 2 procedures, one for initialize and another to reset and 3 functions (store, get total and get values).

CREATE OR REPLACE PACKAGE MergeOptions AS

   PROCEDURE Initialize(v_num in integer);

   Function GetCount(v_num in integer) RETURN NUMBER;
   Function SetValue(v_num in integer, merge_val_in IN varchar2) return varchar2;
   Function GetValues(v_num in integer) return varchar2;

   PROCEDURE Reset;

END MergeOptions;

The idea is store the values instead of the counters as Adrian post and be able to store the values that we want (inserted, updated, deleted or multiple values).
We will have an array (the size depends how many values we want) with the values:

  type typ is record(val varchar2(32767));
  type tab is table of typ;
  array_t tab := tab();

And the procedures to manage this values:

PROCEDURE Initialize(v_num in integer) is
  begin
    array_t.extend(v_num);
end Initialize;
PROCEDURE Reset is
  begin
    array_t := tab();
end Reset;
Function GetCount(v_num in integer) 
    RETURN NUMBER is
    total number := 0;
  begin

    select nvl(max(rownum), 0)
      into total
      from (SELECT TRIM(REGEXP_SUBSTR(array_t(v_num).val, '[^;]+', 1, LEVEL)) AS UpdatedRows
              FROM DUAL
            CONNECT BY TRIM(REGEXP_SUBSTR(array_t(v_num).val,
                                          '[^;]+',
                                          1,
                                          LEVEL)) IS NOT NULL) V
     where V.UPdatedRows is not null;

    return total;
end GetCount;
Function SetValue(v_num in integer, merge_val_in IN varchar2)
    return varchar2 is
  begin
    array_t(v_num).val := array_t(v_num).val || merge_val_in || ';';
    return merge_val_in;
end SetValue;
Function GetValues(v_num in integer) 
    return varchar2 is
  begin
    return array_t(v_num).val;
end GetValues;

This solution is available only for versions greater or equal to 10g. If you are using previous versions you should replace function GetCount to find how many times appear “;” for example.

Ok. Now is time to test it:

declare 

begin

  Mergeoptions2.Initialize(2);

  Merge into ships S
  using (select * from NewShips) NS
  on (S.SHIPGUID = NS.Shipguid)
  when matched then
    update set S.LENGTH = NS.Length,
               S.NAME = case Mergeoptions.SetValue(1, S.Shipguid) when null then S.NAME else S.NAME end
  when not matched then
    insert
      (SHIPGUID, Name, Class, Length)
    values
      (Mergeoptions.SetValue(2, sys_guid()), NS.Name, NS.Class, NS.Length);

  dbms_output.put_line('You have inserted ' || Mergeoptions.GetCount(1) || ' values. The values are: ' || Mergeoptions.GetValues(1));
  dbms_output.put_line('You have updated ' || Mergeoptions.GetCount(2) || ' values. The values are: ' || Mergeoptions.GetValues(2));

end;

We want to know the Guid provided by oracle so we “keep” the guid when we insert the value in the merge. The problem here is, what happend with update? Guid is part of the on clause so we cannot update this value. We update another value with himself but calling the setvalue function to keep the data desired, so our value is registered in the array.

The final result is:

You have inserted 2 values. The values are: F0823C41AD74F038E0430A1FE534F038;F0823C41AD75F038E0430A1FE534F038;
You have updated 4 values. The values are: F0839C11332330DCE0430A1FE53430DC;F0839C11332430DCE0430A1FE53430DC;F0839C11332530DCE0430A1FE53430DC;F0839C11332630DCE0430A1FE53430DC;

Now we know how many rows are inserted and updated and the primary keys provides by the database. We can use this method to get other values, etc.

You can download the example here.

Hello world!


Welcome to my personal WordPress.

After some time programming, teaching people and sharing knowledges i have decided to start to write a blog . In this blog i will to try to help people that start with .Net, TFS, Sql Server, Oracle, Biztalk, Html, Javascript, etc.

My intention is explain all easily and doing examples.

 

And for sure, feel free to copy the post to your blog but referencing my original post. See you soon.