Technical Insights: Azure, .NET, Dynamics 365 & EV Charging Architecture

Month: August 2008 Page 2 of 5

Self Recursive Deleting On self foreign key sql server

I’ve been assigned a task to delete data from a table with a subtree structure which means the foreign key can be contained in another rows in the same table. It’s a self contained foreign key on the same table.

Theoritically when it comes to my mind, i was thinking of recursive delete. But how????I’ve tried to google about it, I found this article from Microsoft. These are coming from Microsoft Article as well.

These are the dummy data that you can play around with in your DB

CREATE TABLE Employees
(empid int NOT NULL,
 mgrid int NULL,
 empname varchar(25) NOT NULL,
 salary money NOT NULL,
 CONSTRAINT PK_Employees_empid PRIMARY KEY(empid))

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 1, NULL, 'Nancy',  $10000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 2,    1, 'Andrew',  $5000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 3,    1, 'Janet',   $5000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 4,    1, 'Margaret',$5000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 5,    2, 'Steven',  $2500.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 6,    2, 'Michael', $2500.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 7,    3, 'Robert',  $2500.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 8,    3, 'Laura',   $2500.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES( 9,    3, 'Ann',     $2500.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES(10,    4, 'Ina',     $2500.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES(11,    7, 'David',   $2000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES(12,    7, 'Ron',     $2000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES(13,    7, 'Dan',     $2000.00)

INSERT INTO employees(empid, mgrid, empname, salary)
  VALUES(14,   11, 'James',   $1500.00)

I’m going to delete employee no 3(Janet) which means it need to delete 7(Robert),8(Laura),9(Ann) and 11(David),12(Ron),13(Dan), 14(James) based on the managerial structure level.

What you need to do is to create a trigger for cascading delete

CREATE TRIGGER trg_d_employees_on_delete_cascade ON Employees FOR DELETE
AS

IF EXISTS(SELECT *
          FROM
              Employees AS E
            JOIN
              deleted   AS D ON E.mgrid = D.empid)

  DELETE FROM Employees
  FROM
      Employees AS E
    JOIN
      deleted   AS D ON E.mgrid = D.empid

  GO

It will self join based on the deleted table. It’s not finish yet, you need to set the recursive trigger to active by executing command like

ALTER DATABASE DMO
SET RECURSIVE_TRIGGERS ON

Action Time:

DELETE FROM employees WHERE empid = 3

and you will see that it deletes all the subordinates of Janet

How to remove checked item in Checked Box List

At the moment, I’m learning towards win development. I got a very simple problem which is “Removing checked item on checked box list”. The first code below is throwing an error since you try to delete an item then on the postback it will reset the index. The real solution is on the second code

//this code is throwing an error about the index position
 private void btnRemove_Click(object sender, EventArgs e)
        {
            foreach (SMSData item in chkSmsList.CheckedItems)
            {
                chkSmsList.Items.Remove(item);
            }
        }

Fix

//this is the code which is working perfectly, basically this code always looking into the first item on the "CheckedItems" Stack
  private void btnRemove_Click(object sender, EventArgs e)
        {
            while (chkSmsList.CheckedItems.Count > 0)
            {
                chkSmsList.Items.Remove(chkSmsList.CheckedItems[0]);
            }
        }

Filtering Field/Column in DataTable

I was having a problem when I have the same datatable and one datagrid but I want to display different field on the grid for different report and I want to use AutoGenerateColumn = true in the datagrid. Remember, it is about filtering fields not Row(If you want to filter row then you can use dataview).

This is the way of filtering field in datatable

     public static DataTable FilterTableRemoveColumns(tdsReports.ReportSelectDataTable inputTable, List fields)
        {
            //create a new data table
            DataTable newTable = new DataTable();
            newTable.TableName = "newtable";

            //iterate through each column
            foreach (DataColumn col in inputTable.Columns)
            {
                //cross match and filter fields/column
                if (fields.Contains(col.ColumnName))
                {
                    //create a new datacolumn with the same column name and same datatype
                    DataColumn newCol = new DataColumn(col.ColumnName, col.DataType);
                    newTable.Columns.Add(newCol);
                }
            }

            //you ignore the schema because you don't want to throw the exception
            //you merge the data with the new schema
            newTable.Merge(inputTable, true, MissingSchemaAction.Ignore);
            return newTable;
        }

this is how you use it. You pass a string list into the function. The string list contains your desired column

Private Function FilterDataTableColumn(ByVal dtReport As tdsReports.ReportSelectDataTable) As DataTable

        Dim dt As DataTable = New DataTable()
        Try
            Dim list As List(Of String) = New List(Of String)

            If (ReportType = Enums.ReportType.DispatchedOrdersReport) Then
                list.Add("OrderID")
                list.Add("PaymentType")
                list.Add("ProductCode")
                list.Add("Qty")
                list.Add("Price")
                list.Add("Total")
                list.Add("IncGst")

            ElseIf (ReportType = Enums.ReportType.MonthySalesReport) Then
                list.Add("Qty")
                list.Add("ProductCode")
                list.Add("ProductName")

            ElseIf (ReportType = Enums.ReportType.OrderReport) Then
                list.Add("ProductCode")
                list.Add("Qty")
                list.Add("ProductName")

            End If

            dt = objReportService.FilterTableRemoveColumns(dtReport, list)

        Catch ex As Exception

        End Try

        Return dt
    End Function

Set Default value with clear text for input type=”password”

Normally we have two text boxes which is user name and password. On the first load of the page we want to set the default value of user name text box becoming ‘username’ and set the default value of password text box becoming ‘password’ not ‘*******’.

Well what most of us think that we can use javascript to change the type of the input box?well I’ve got this trick to have two textboxes in the same location and swap it with “OnFocus” event

  
            

    

Set the default value for username text box via code behind

      Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            txtUserName.Attributes.Add("onfocus", "JavaScript:if(this.value=='username'){this.value=''};")
            txtUserName.Attributes.Add("onblur", "JavaScript:if(this.value==''){this.value='username'};")
            txtUserName.Attributes.Add("value", "username")

            txtPassword.Attributes.Add("onkeydown", _
                                            "javascript:if((event.which && event.which == 13) || " _
                                            + "(event.keyCode && event.keyCode == 13))" _
                                            + " {document.getElementById('" + btnLogin.ClientID + "').click(); " _
                                            + " return false; } else return true;")
        End Sub

Temporary View using Common Table Expression In Sql server 2005

In this post, I will discuss on how to optimize join. Based on my experience. When you join record you need to join as fewer as possible otherwise it will result in performance. And please make sure you put the index on the key that you are using for join.

Within SQL Server 2005, You can use temporary view, It is not a table variable and it is not a temporary table. You also need to try to avoid cursor as well if possible.

First sample is a traditional join where I joined all the tables that required. In this sample EvenResult table has 20 million rows and I need to count the evenresult table based on the EventID that I get from the join criteria.

1. Join all tables./Traditional Way and it takes about 21secs

    SELECT
                E.EventID
            FROM
                Events E
            INNER JOIN
                Venues V
            ON
                E.VenueID = V.VenueID
            INNER JOIN
                Regions R
            ON
                R.RegionID = V.RegionID
            INNER JOIN
                EventResults er
            ON
                E.EventID = er.EventID
            WHERE
                (DATEDIFF(d, E.EventDate, @DateFrom) = 0)
            AND
                ((@StateID IS NULL) OR (R.StateID = @StateID))
            AND
                ((@RegionID IS NULL) OR (R.RegionID = @RegionID))
            AND
                ((@VenueID IS NULL) OR (V.VenueID = @VenueID))
            AND
                ((@EventScheduleID IS NULL) OR (E.EventScheduleID = @EventScheduleID))

2. Using Temporary Views, In this query. I try to filter down all the required eventID based on the criteria and insert it into a temporary view(tblEvents). Once i get the filtered result then I joined it with EventResults table and It takes only 16secs considering the number of records.

WITH tblEvents(EventID) AS
(
            SELECT
                E.EventID
            FROM
                Events E
            INNER JOIN
                Venues V
            ON
                E.VenueID = V.VenueID
            INNER JOIN
                Regions R
            ON
                R.RegionID = V.RegionID
            WHERE
                (DATEDIFF(d, E.EventDate, @DateFrom) = 0)
            AND
                ((@StateID IS NULL) OR (R.StateID = @StateID))
            AND
                ((@RegionID IS NULL) OR (R.RegionID = @RegionID))
            AND
                ((@VenueID IS NULL) OR (V.VenueID = @VenueID))
            AND
                ((@EventScheduleID IS NULL) OR (E.EventScheduleID = @EventScheduleID))
)

            SELECT
                COUNT(*) As Total
            FROM
                tblEvents te
            INNER JOIN
                EventResults er
            ON
                te.EventID = er.EventID
            GROUP BY
                er.MemberID
            HAVING
                COUNT(*) >= @MinGame
            AND
                COUNT(*) <= @MaxGame

Error System.NotSupportedException: The given path’s format is not supported

I got this exception when i tried to uploading a file to a web and try to save it as a different name

System.NotSupportedException: The given path’s format is not supported.
at System.Security.Util.StringExpressionSet.CanonicalizePath(String path, Boolean needFullPath)
at

By using code below it will make sure that you will get the real file name without any trailing path, fuCSV is a file upload control and there is a property file name but it doesn’t guarantee that you will get the actual file name. When i tried to debug it, it also give me the file path. The best way of doing this is to use GetFileName method from System.IO.Path

It was:

string filename = fuCSV.PostedFile.FileName;

Fix

string filename = System.IO.Path.GetFileName(fuCSV.PostedFile.FileName);

Record/Row Filter in DataTable

When I have a smaller rows return from my sql stored procedure, I tend to think of not recreating another stored procedure to do filtering or to use optional parameter. My idea is to do filtering from the code base and not recreating/adding the stored procedure.

The idea was to create a generic stored procedure without any filter and apply the filter from the code base. The example given is by applying filter to dataset and then after that add the datatable to dataset and then cast it back again to the datatable.

  public tdsEvent.EventSummaryDataTable TodayEventSummaryFilter(string filter)
        {
            tdsEvent.EventSummaryDataTable table = TodayEventSummaryCache();
            DataRow[] rows = table.Select(filter); //apply the filter first

            if (rows.Length != 0)
            {
                DataSet ds = new DataSet();

                tdsEvent.EventSummaryDataTable eventTable = new tdsEvent.EventSummaryDataTable();
                ds.Tables.Add(eventTable); // add to the filter
                ds.Merge(rows, false, MissingSchemaAction.Ignore);
                // cast it back to the data table
                table = ds.Tables[0] as tdsEvent.EventSummaryDataTable;
            }
            else
            {
                table = new tdsEvent.EventSummaryDataTable();
            }

            return table;
        }

This is the alternative code which doing the same thing as above

Dim table as tdsEvent.EventSummaryDataTable = TodayEventSummaryCache()
//create dataview instance based on datatable

dim dv as DataView = new DataView(table)

//create the filter to select the valid only
dv.RowFilter = "Valid = 1"

//bind to the grid or repeater
rptEvent.Datasource = dv
rptEvent.DataBind()

ORDER BY in UNION

I was having a problem this morning in using a ORDER BY in UNION Clause. The solution is to use keyword of “TOP 100 PERCENT” on the related ORDER BY SELECT query.

CREATE PROCEDURE MyAPLRank
@MemberID int
AS
      SET NOCOUNT ON;
BEGIN
      SELECT r.ResultName,r.PlayerOfTheYearID,r.MemberID,r.RankID,r.memberCode,
            r.FirstName,r.Surname,r.State,r.NumEvents,r.Points,r.AvgPoints,
                  r.MeetsRequirements,r.Valid,r.IsLeaderBoard,r.RowNum
      FROM
      (
            SELECT
                  'Player of The Year' As ResultName,PlayerOfTheYearID,MemberID,
                  RankID,memberCode,FirstName,Surname,State,NumEvents,Points,
                  AvgPoints,MeetsRequirements,Valid,'0' as IsLeaderBoard,1 as RowNum
            FROM
                  PlayerOfTheYearQuery
            WHERE
                  PlayerOfTheYearID
                  =
                  (
                        SELECT
                              TOP 1 poy.PlayerOfTheYearID
                        FROM
                              PlayerOfTheYear poy
                        INNER JOIN
                              Schedule s
                        ON
                              (s.ScheduleID = poy.ScheduleID)
                        WHERE
                              (s.MonthID IS NULL AND s.WeekID IS NULL AND s.QuarterID IS NULL)
                        ORDER BY
                              s.ScheduleID
                        DESC
                  ) AND MemberID = @MemberID AND MeetsRequirements = 1
            UNION
            SELECT
                  'Player of The Month' As ResultName,PlayerOfTheYearID,MemberID,
                  RankID,memberCode,FirstName,Surname,State,NumEvents,Points,
                  AvgPoints,MeetsRequirements,Valid,'0' as IsLeaderBoard,2 as RowNum
            FROM
                  PlayerOfTheYearQuery
            WHERE
                  PlayerOfTheYearID
                  =
                  (
                        SELECT
                              TOP 1 poy.PlayerOfTheYearID
                        FROM
                              PlayerOfTheYear poy
                        INNER JOIN
                              Schedule s
                        ON
                              (s.ScheduleID = poy.ScheduleID)
                        WHERE
                              (s.MonthID IS NOT NULL AND s.WeekID IS NULL)
                        ORDER BY
                              s.ScheduleID
                        DESC
                  ) AND MemberID = @MemberID AND MeetsRequirements = 1
            UNION
            SELECT
                  'Player of The Week' As ResultName,PlayerOfTheYearID,MemberID,
                  RankID,memberCode,FirstName,Surname,State,NumEvents,Points,
                  AvgPoints,MeetsRequirements,Valid,'0' as IsLeaderBoard,3 as RowNum
            FROM
                  PlayerOfTheYearQuery
            WHERE
                  PlayerOfTheYearID
                  =
                  (
                        SELECT
                              TOP 1 poy.PlayerOfTheYearID
                        FROM
                              PlayerOfTheYear poy
                        INNER JOIN
                              Schedule s
                        ON
                              (s.ScheduleID = poy.ScheduleID)
                        WHERE
                              (s.MonthID IS NOT NULL AND s.WeekID IS NOT NULL)
                        ORDER BY
                              s.ScheduleID
                        DESC
                  ) AND MemberID = @MemberID  AND MeetsRequirements = 1
      UNION

                SELECT TOP 100 PERCENT
                         v.venue As ResultName,l.leaderboardID as PlayerOfTheYearID,lq.MemberID,
                         lq.RankID,lq.membercode,lq.name as FirstName,lq.name as Surname,s.State,
                        lq.NumEvents,lq.Points,lq.points as AvgPoints,lq.valid as MeetsRequirements,
                        lq.Valid, '1' as IsLeaderBoard,4 as RowNum
                FROM
                        leaderboardquery lq
                INNER JOIN
                        leaderboard l
                ON
                        (
                                l.leaderboardid = lq.leaderboardid
                            AND
                                l.venueid IS NOT NULL
                            AND
                                lq.MemberID = @MemberID
                            AND
                                l.scheduleID =
                                        (
                                         SELECT    ScheduleID
                                         FROM    Schedule
                                         WHERE    GETDATE() BETWEEN FromDate AND ToDate
                                                AND MonthID IS NOT NULL
                                        )
                        )
                INNER JOIN
                        venues v
                ON
                        (v.venueID = l.venueid)
                INNER JOIN
                        states s
                ON
                        l.StateID = s.StateID
                ORDER BY
                    l.ScheduleID
                DESC
      ) r
ORDER BY
      RowNum
END

Casting DataItem in repeater to strongly typed dataset

Most of the time when you use repeater, you want to be able to cast the datasource/dataitem, you don’t really want to do DataBinder.Eval(e.Item.DataItem, “Description”) but you want to do row.Description. It’s not hard to do that, this is the snippet

Protected Sub rptEvents_Repeater(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles rptEvents.ItemDataBound
        If (e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem) Then

             'you need to cast eh dataitem into datarowview and cast them again to strongly type dataset

            Dim view As DataRowView = DirectCast(e.Item.DataItem, DataRowView)
            Dim row As tdsEvent.EventSummaryRow = DirectCast(view.Row, tdsEvent.EventSummaryRow)

            If Not (row Is Nothing) Then

                Dim lblVenue As Label = DirectCast(e.Item.FindControl("lblVenue"), Label)
                Dim lblEvent As HyperLink = DirectCast(e.Item.FindControl("lblEvent"), HyperLink)
                Dim lblState As Label = DirectCast(e.Item.FindControl("lblState"), Label)
                Dim lblTime As Label = DirectCast(e.Item.FindControl("lblTime"), Label)
                Dim lblType As Label = DirectCast(e.Item.FindControl("lblType"), Label)

                Dim eventClass As String = row.ColorCode ' don't set free

                ' if event is not normal, set it...
                If Not (row.IsVenueNull()) Then
                    lblVenue.Text = row.Venue
                End If

                If Not (row.IsEventNull()) Then
                    lblEvent.Text = Left(row.Event, 25) + "..."
                    lblEvent.NavigateUrl = String.Format("~/playpoker/view-event.aspx?EventID={0}&EventTypeID={1}", row.EventID.ToString(), row.EventTypeID.ToString())
                End If

                If Not (row.IsStateNull()) Then
                    lblState.Text = row.State
                End If

                If Not (row.IsEventTypeNull()) Then
                    lblType.Text = row.EventType
                End If

                If Not (row.IsRegistrationTimeNull()) Then
                    lblTime.Text = row.RegistrationTime.ToString("hh:mm tt")
                End If

                'bind all the data...

                'set class's
                If Not (String.IsNullOrEmpty(eventClass)) Then
                    lblVenue.CssClass = eventClass
                    lblEvent.CssClass = eventClass
                    lblState.CssClass = eventClass
                    lblTime.CssClass = eventClass
                    lblType.CssClass = eventClass
                End If

            End If
        ElseIf (e.Item.ItemType = ListItemType.Header) Then

            Dim lnk As LinkButton = DirectCast(e.Item.FindControl("lnkVenue"), LinkButton)

            If Not (lnk Is Nothing) Then
                lnk.CommandName = "SortCommand"
                lnk.CommandArgument = "Venue"
            End If

            lnk = DirectCast(e.Item.FindControl("lnkEvent"), LinkButton)

            If Not (lnk Is Nothing) Then
                lnk.CommandName = "SortCommand"
                lnk.CommandArgument = "Event"
            End If

            lnk = DirectCast(e.Item.FindControl("lnkState"), LinkButton)

            If Not (lnk Is Nothing) Then
                lnk.CommandName = "SortCommand"
                lnk.CommandArgument = "State"
            End If

            lnk = DirectCast(e.Item.FindControl("lnkTime"), LinkButton)

            If Not (lnk Is Nothing) Then
                lnk.CommandName = "SortCommand"
                lnk.CommandArgument = "lnkTime"
            End If

            lnk = DirectCast(e.Item.FindControl("lnkType"), LinkButton)

            If Not (lnk Is Nothing) Then
                lnk.CommandName = "SortCommand"
                lnk.CommandArgument = "EventType"
            End If

        End If
    End Sub

How to filter and sort in Dataset

Here is the way to filter or to sort dataset and then you can bind into your datagrid

              If intEventID = 0 Then
                ds = DataAccess.Events.GetAllEventsByRegionID(Me.radStartDate.SelectedDate, Me.radEndDate.SelectedDate, intRegionID, intVenueID)

            Else
                ds = DataAccess.Events.GetEventByIDDS(intEventID)
            End If

            'this is used to show the valid event only
            Dim eventView As DataView
            eventView = ds.Tables(0).DefaultView
            eventView.RowFilter = "Valid = true"

            'this is used to sort
            eventView.Sort = "EventID Desc"

           grdEvents.DataSource = eventView

Page 2 of 5

Powered by WordPress & Theme by Anders Norén