【问题标题】:how to Check 1st,2nd and 3rd row togther in datatable c# asp.net? [closed]如何在数据表c#asp.net中同时检查第一、第二和第三行? [关闭]
【发布时间】:2018-10-19 17:56:23
【问题描述】:

我有一个这样的表结构(如图所示) 我想要像这样的条件
如果第一行应该是 (authlevel=1,authorized=1) AND
第 2 行(authlevel=2 且授权=0 或 null)AND
第 3 行(authlevel=3 和(authorized=0 或 null))和

我尝试了下面的代码但无法理解。

    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.
       }
}

【问题讨论】:

  • Dictionary 未排序,1st element of dictonary lstuserCH 是什么意思
  • 它包含 2 个元素,我想要第一个元素(在里面,否则它应该保持原样
  • 第一个值@Valentin

标签: c# asp.net datatable datarow


【解决方案1】:

您可以选择个人行并执行如下业务逻辑:

    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
        }
    }

【讨论】:

  • 在 if 条件下只取字典的第一个值的任何方式
  • 我认为一个更好的问题是问这个问题:有没有更好的方法来识别每一行,而不是期望它们以特定的顺序进入你的函数?
【解决方案2】:

这里有几个你可以采取的不同角度。

首先,您可以编写一个函数,该函数接受一个 DataTable 并返回它是否拥有某个授权级别:

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.
}

...然后,您的逻辑很简单:

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

这种方法的最大优势是什么?它不假设结果数据表中行的顺序 - 硬编码 row[0]、row[1]、row[2] 的缺点是假设所有行都存在并且以特定顺序存在。此外,它很好并且经过重构,因此逻辑非常清晰简洁。

第二种方法是在 SQL 端很好地格式化数据。我的意思是,您没有理由必须从 C# 跨多行进行解码。

-- 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

... 也就是,不要取回三行并尝试在 C# 端解析它,只需更改从 SQL 获取数据的方式,以便在单行中取回数据。

无论如何,希望对您有所帮助! :-)

***** 编辑,基于 OP 的 cmets:*****

正如一些人所提到的,Dictionary 对象是可靠排序的。这不是你应该依赖的东西。 (见Does the Enumerator of a Dictionary<TKey, TValue> return key value pairs in the order they were added?

简短的故事:如果您继续使用 Dictionary 对象,那么当订单没有像您期望的那样返回时,您将被烧毁。

但这没关系 - 你可以转移到其他东西。两个不错的选择是:

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

好的,既然我已经摆脱了那么大的谨慎?您可以使用一些不错的方便的 Linq 函数来获取您要查找的内容:

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

如果这没有意义,请在谷歌上搜索“C# List Take”、“C# IEnumerable ToList”等。

【讨论】:

  • 感谢任何想法如何在 IF 条件下只有第一个字典值,否则它将保持不变?
  • 你必须更清楚一点。您是要将值放入字典中,还是从字典中读取
  • 实际上我想在 if 条件下操作字典,它只包含第一个值,否则它应该保持原样。 @凯文
  • 这本词典是在别处创建的吗?或者你想创建一个新字典,基于他们是否有 AuthLevels 2 和 3?我问的原因是因为在您的代码中,您在 IF 条件之后立即声明了一个新的 Dictionary 对象。
  • 在 if 之前创建。如果我只想要第一个元素,否则它应该保持原样!
猜你喜欢
  • 2021-12-06
  • 2020-06-16
  • 1970-01-01
  • 2022-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多