Wednesday, March 23, 2016

How to Update DataTable and Commit it to the Database

In SSIS Script Task, it seems helpful to use a select statement to consturct a DataTable, update the DataTable as necessary, and commit the DataTable back to database's table. Below is a working example of this case.

protected int updateDeathLog()
{
    int retVal = 0;
    string connString = Dts.Variables["ConnString1"].Value.ToString();
    string sql = "SELECT ObjectId, NewFileName, PageNum, TargetFileExists, TargetFileExistsDT " +
            "FROM MyTable WHERE SourceFileExists = 1 AND TargetFileExists = 0";

    using (SqlConnection conn = new SqlConnection(connString))
    {
        try
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(sql, conn);
            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
            string newFileFullPath = String.Empty;

            DataTable dt = new DataTable();
            adapter.Fill(dt);
            foreach(DataRow row in dt.Rows)
            {
                // If files exists in target folder, update flags and 
                // datetime field in the DataTable.
                newFileFullPath = Dts.Variables["TargetFolderDeath"].Value.ToString()
                  + "\\" + row["NewFileName"].ToString();

                if(File.Exists(newFileFullPath))
                {
                    row["TargetFileExists"] = true;
                    row["TargetFileExistsDT"] = DateTime.Now;
                }
                else
                {
                    row["TargetFileExists"] = false;
                    row["TargetFileExistsDT"] = System.DBNull.Value;
                }
            }

            // Commit update DataTable to the MyTable.
            // Prior to the commit, set up primary keys in the DataTable 
            // and create a CommandBuilder.
            DataColumn[] keyColumns = new DataColumn[2];
            keyColumns[0] = dt.Columns["ObjectId"];
            keyColumns[1] = dt.Columns["PageNum"];
            dt.PrimaryKey = keyColumns;

            SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(adapter);
            adapter.Update(dt);

            retVal = dt.Rows.Count;
        }
        catch (Exception ex)
        {
            retVal = -1;
            errorMsg = ex.Message;
            stackTrace = ex.StackTrace;
        }
    }

return retVal;
}

Tuesday, March 15, 2016

Change [all files and folders] of a [directory] to 644 and 755

I came across a situation to run chmod 755 [folder] and chmod 644 [file] on my php dev folder. The following would handle all files and folders of current working folder.

sudo find . -type f -exec chmod 644 {} \;
sudo find . -type d -exec chmod 755 {} \;

Thursday, March 10, 2016

Use Bootstrap Popover to load external content through Ajax

It seemed easy to load an external contents through Ajax onto Bootstrap Popover at first. In fact, it wasn't as straightforward as I would like.
Using the content() function, it is straightforward to load any static content.
<a class="pop">Link</a>
<div id="contentDiv" style="display:none;">Some content...</div>

<script type="text/javascript">
$('.pop').popover({
    html: true,
    content: function(){
        return $('#contentDiv').html();
    }
});
</script>
However, loading an external content dynamically through Ajax plus "Loading ..." message took some thoughts.
<a class="pop" href="Product/100">Link</a>

<script type="text/javascript">
$('.pop').popover({
    html: true,
    content: function(){
        // Create a random temporary id for the content's parent div
        // with a unique number just in case.
        var content_id = "content-id-" + $.now();

        $.ajax({
            type: 'GET',
            url: $(this).prop('href'),
            cache: false,
        }).done(function(d){
            $('#' + content_id).html(d);
        });

        return '<div id="' + content_id + '">Loading...</div>';

        // Initially, the content() function returns a parent div, 
        // which shows "Loading..." message.
        // As soon as the ajax call is complete, the parent div inside 
        // the popover gets the ajax call's result.

    }
});
</script>

Keeping the Bootstrap Popover alive while mouse moves from triggering element to the popover

I tried to use the Bootstrap Popover as a quick dynamic ajax form within which I can perform further actions. By default, when popover appears as a result of hovering over the triggering element, it disappears when the triggering element is no longer hovered.

One easy way to keep the popover stay put until I am no longer hovering over the triggering element or the popover itself is to use { trigger: "manual", html: true, animation: false } and handle the trigger via "mouseenter" and "mouseleave" event.

// the triggering element has class of 'pop'
$(".pop").popover({
    trigger: "manual", 
    html: true,
    animation: false
}).on("mouseenter", function(){
    var _this = this;
    $(this).popover("show");
    $(".popover").on("mouseleave", function(){
      $(_this).popover('hide');
    });
}).on("mouseleave", function(){
    var _this = this;
    setTimeout(function(){
      if (!$(".popover:hover").length){
        $(_this).popover("hide");
      }
    }, 50); 
    // If popover is not hovered within 50 milliseconds 
    // after the mouse leaves the triggering element, 
    // the popover will be hidden. 
    // 50 milliseconds seem fine in most cases.
});

Thursday, March 3, 2016

@Html.CheckBoxFor( ) helper method problem when posting to Controller method with Bind(Include=...) annotation

@Html.CheckBoxFor(model => model.IsDeposit) will generate html
<input type="checkbox" name="IsDeposit" value="true" />
<input type="hidden"   name="IsDeposit" value="false" />
given that IsDeposit is a boolean value. Then the form is submitted to a method in controller such as
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include ="PaymentID,IsDeposit")] Payment payment)
{ . . . }        
The problem is that the checkbox value will always be false whether the checkbox is checked or not.

The cause of this problem seems to be the IsDeposit in the Bind(Include=...) annotation is not handled properly yet in ASP.NET MVC. @Html.CheckBoxFor(..) creates two elements with the same name attribute (checkbox and hidden). Possibly only the hidden element is accepted to the method when Bind(Include=..) is used. I tried including "IsDeposit" twice (for example, Bind[Include=IsDeposit,IsDeposit,,]) just in case, but it did not help.

The best bet is to avoid using the Bind(Include=...) annotation when @Html.CheckBoxFor() helper method is used. Alternatively, you can also create the checkbox element manually yourself instead of using the helper method @Html.CheckBoxFor(). For example,
<input type="checkbox" name="IsDeposit" id="IsDeposit" value="true" />