2

i have a table structure like this (shown in image) and i want like somecondition like this
if 1st row should be (authlevel=1,authorized=1) AND
row 2 (authlevel=2 and authorized=0 or null) AND
row 3 (authlevel=3 and (authorized=0 or null)) AND

i have tried the code below but not able to understand.

    Dictionary<string, BO.User> lstuserCH = new Dictionary<string, BO.User>();
            foreach (DataRow row1 in _data.wsm_PurchaseOrder_Auth) {
                if (((Convert.ToInt32(row1("AuthLevel")) == 1) 
                            && !row1.IsNull("Authorised"))) {
                    // here i need only the 1st element of dictonary lstuserCH

                }
      else
       {
      //dictionary lstuserCH should be remain as it is.
       }
}

table structure

2 Answers2

1

Here's a couple of different angles you could take.

First up, you could program a function that takes in a DataTable and returns back whether it possesses a certain authorization level:

bool AuthorizedForLevel(DataTable recordsForPONumber, int authLevel)
{
    foreach(DataRow dr in recordsForPONumber.Rows)
    {
        if (dr.Field<int>("AuthLevel") == authLevel)
        {
            int? authorized = dr.Field<int?>("Authorized");
            if (!authorized.HasValue) return false;
            if (authorized.Value == 0) return false;
            return true;
        }
    }
    return false; // didn't have an entry, so they must not be authorized.
}

... and then, your logic is simply:

if (AuthorizedForLevel(resultDT, 1))
    if (!AuthorizedForLevel(resultDT, 2))
        if (!AuthorizedForLevel(resultDT, 3))
            // what you want to do

The big advantage to this approach? It doesn't assume the order of the rows in your result datatable - hard coding row[0], row[1], row[2] has the disadvantage of assuming that all the rows are present and in a specific order. Additionally, it's nice and refactored, so the logic is very clear and concise in what's going on.

A second approach would be to format the data nicely on the SQL side. I mean, there's no reason you have to do the decoding from the C# across multiple rows.

-- some variable @poNum that's passed to your stored procedure
select
   (select Authorized from myTable where PONumber = @poNum and AuthLevel = 1) as AuthorizedFor1,
   (select Authorized from myTable where PONumber = @poNum and AuthLevel = 2) as AuthorizedFor2,
   (select Authorized from myTable where PONumber = @poNum and AuthLevel = 3) as AuthorizedFor3

... aka, instead of getting three rows back and trying to parse it on the C# side, just change how you're getting the data from SQL so that you get back your data in a single row.

Anyway, hope that helps out! :-)

***** Edit, based on OP's comments: *****

As a few people have mentioned, Dictionary objects are NOT reliably sorted. It's not something you should depend on. (See Does the Enumerator of a Dictionary<TKey, TValue> return key value pairs in the order they were added?)

Short Story: If you continue forward using a Dictionary object, you're going to get burned in the future when the order doesn't come back like you expect it to.

But that's okay - you can shift over to something else. Two good options would be:

List<Tuple<string, BO.User>> versionA;
List<KeyValuePair<string, BO.User>> versionB;

Okay, now that I've gotten that big caution out of the way? You can use some nice handy Linq functions to get what you're looking for:

List<Tuple<string, BO.user>> listICareAbout;
if (someCondition)
    listICareAbout = myMainList.Take(1).ToList();
else
    listICareAbout = new List<Tuple<string, BO.user>>(myMainList);

If that doesn't make sense, do some googling for 'C# List Take', 'C# IEnumerable ToList', etc.

Kevin
  • 2,133
  • 1
  • 9
  • 21
  • thanks any idea how to have only 1st value of dictionary in IF condition else it would remain same ? –  May 09 '18 at 16:13
  • You'll have to be a bit more clear. Are you wanting to put values *into* the dictionary, or read *from* the Dictionary? – Kevin May 09 '18 at 16:32
  • actually i want to manipulate dictionary in if condition where it will contain the 1st value only and in else it should be remain as it is. @kevin –  May 09 '18 at 16:35
  • Is this dictionary created elsewhere? Or do you want to create a new dictionary, based on whether they have AuthLevels 2 and 3? The reason I'm asking is because in your code, you're declaring a new Dictionary object right after your IF conditions. – Kevin May 09 '18 at 16:46
  • created before the if. in IF i want the 1st element only otherwise it should be remain as it !! –  May 09 '18 at 16:48
  • Added to my answer based on your comments. – Kevin May 09 '18 at 17:01
0

You can select individuals rows and perform business logic like this:

    public void ValidateFirstThreeRows(DataTable dt)
    {
        if (dt.Rows.Count < 3)
        {
            // Handle this case
        }
        var row1 = dt.Rows[0];
        var row2 = dt.Rows[1];
        var row3 = dt.Rows[2];

        if ((int)row1["AuthLevel"] == 1
            && bool.TryParse(row1["Authorized"]?.ToString(), out bool result)
            && (int)row2["AuthLevel"] == 2
            && bool.TryParse(row2["Authorized"]?.ToString(), out result)
            && (int)row3["AuthLevel"] == 3
            && bool.TryParse(row3["Authorized"]?.ToString(), out result))
        {
            // Do your stuff
        }
    }
null
  • 153
  • 1
  • 3
  • 16
  • any way to take only 1st value of dictonary in if condition –  May 09 '18 at 15:34
  • I think a better question is to ask this: is there some better way to identify each row, rather than expecting them to come into your function in a specific order? – null May 09 '18 at 15:41