如何根据字段值从另一个数据表填充数据表

时间:2013-01-06 13:24:10

标签: c# asp.net datatable

我教了一个9个单元的课程,学生可以通过每个单元的'通行证','功绩'或'区别'。 P获得70分,M获得80分,D获得90分。一年中的总体结果是所有单位的总和。

他们需要在允许“M”标准之前通过所有“P”标准,并且在允许“D”标准之前他们需要所有“M”标准。 P / M / D标准的数量取决于单位。下面的学生已经为这个单位取得了“通过”(70分),因为即使他得到了所有D标准,他也失败了:

第1单元 - 脑部手术

P1 - 知道大脑的位置 - 通过
P2 - 知道哪条路向上 - 通过
M1 - 解释大脑的作用 - 通过
M2 - 男性和女性大脑之间是否存在差异 - 失败 D1 - 弄清楚为什么我的大脑无法解决这个问题 - 通过
D2 - 发明一种药物,让大脑立即弄清楚逻辑 - 通过
D3 - 找到一种通过智力赚取大量资金的方式 - 传递

我有一个SqlDataReader,用这些列填充DataTable:unitNo,criterionName,criteriontype(即P / M / D),passedOrFailed。查询已经由个别学生选择,因此DataTable仅包含一个学生的记录。它看起来像这样:

UnitNo   Citerion   Type   passed?  
1        know etc     P       Yes  
1        know etc     P       Yes  
1        explain etc  M       Yes  
1        is there etc M       No  
1        Figure etc   D       Yes  
1        invent etc   D       Yes  
1        find etc     D       Yes  
2        blah etc     P       Yes  
2        wot etc      P       Yes  
2        so etc       M       No 

我正在使用看起来像这样的DataTable:

UnitNo  P    M   D   Points  
1       Y    N   Y     70  
2       Y    Y   N     80  
3       N    N   N      0  
4       N    Y   Y      0  
5       Y    Y   Y     90  

...
...
...........................

最后得分 - 学生有240分。

我对DataTables,c#等完全没问题,这是我正在进行的爆破逻辑。我编写的每一段代码在大约2行之后看起来像意大利面。

有没有人有一些指针可以排除这个逻辑?这就像Ghormenghast学校的一个场景......如果你能解决它,那么我将亲自派妻子来为你做一个星期天的烤肉。

PC


好的,这是包含CSharper答案的实际代码(也编辑为添加他的额外列名称的解决方案)。这显然是正确的解决方案,我只是没有完全显示数字(我发现他在DataRow演员之后省略了括号,但这不是问题)。我在最后勾上了几个测试网格以显示结果。此外,我不是一个linq家伙所以我不知道如何将第一个表格中的单位名称添加到第二个表格,或者总点数:

(注意,我使用1 =未标记,2 =失败,3 =传递passFail字段)

//create the sql to extract the data
        String sqlString = "SELECT unitNo, unitName, criterionPMD, passFail FROM unitDetails INNER JOIN unitStudentRecord ON unitDetails.id = unitStudentRecord.unitDetailsId INNER JOIN unitSummary ON unitDetails.unitSummaryId = unitSummary.id WHERE studentID = '" + ((String)Session["studentID"]).Trim() + "'";
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["studentTutorialsConnectionString"].ConnectionString);
        SqlCommand sqlComm = new SqlCommand(sqlString, conn);
        conn.Open();
        SqlDataReader sqlTotalMarks = sqlComm.ExecuteReader();

        //create the workings out datatable and fill it
        DataTable dtWorkings = new DataTable();
        dtWorkings.Load(sqlTotalMarks);
        conn.Close();

        // create the results datatable
        DataTable dtResults = new DataTable();
        dtResults.Columns.Add("units", typeof(int));
        dtResults.Columns.Add("name", typeof(string));
        dtResults.Columns.Add("P", typeof(bool));
        dtResults.Columns.Add("M", typeof(bool));
        dtResults.Columns.Add("D", typeof(bool));
        dtResults.Columns.Add("points", typeof(int));

        //fill the results table
        foreach (var units in dtWorkings.Rows.Cast<DataRow>().GroupBy(r => r["unitNo"]))
        {
            var p = units.Where(r => r["criterionPMD"] == "P").All(r => r["passFail"] == "3");
            var m = units.Where(r => r["criterionPMD"] == "M").All(r => r["passFail"] == "3");
            var d = units.Where(r => r["criterionPMD"] == "D").All(r => r["passFail"] == "3");
            dtResults.Rows.Add(
                 units.Key,//UnitNo
                 units.Select(r => r["unitName"]).First(),//UnitName                    
                 p,
                 m,
                 d,
                 p ? (m ? (d ? 90 : 80) : 70) : 0);//Points
        }

        gvTemp.DataSource = dtWorkings;
        gvTemp.DataBind();
        gvSummary.DataSource = dtResults;
        gvSummary.DataBind();

这是gvTemp的网格:

   unitNo   unitName       criterionPMD passFail
    2     Computer systems  P     3
    2     Computer systems  P     1
    3     Web rubbish           P     3

这是gvSummary的网格:

units   name               P     M  D   points
2           Computer systems            90   
3           Web rubbish                             90

在gvSummary网格中,勾选所有PMD条件的复选框,但不显示总计。我预计单位2为零,单位3为70分......

非常接近......

1 个答案:

答案 0 :(得分:1)

使用C#类执行此操作可能有助于将问题构建为更小的部分,并且可以更好地维护解决方案。当然,使用DataTable也是可能的。数据表的另一个缺点是数据不易实现类型安全。在这个答案的第一个版本中,r [“criterionPMD”]对字符串的强制转换缺失,因此存在引用比较而不是字符串比较。

            //create the workings out datatable and fill it
            DataTable dtWorkings = new DataTable();
            dtWorkings.Columns.Add("unitNo", typeof(int));
            dtWorkings.Columns.Add("unitName", typeof(string));
            dtWorkings.Columns.Add("criterionPMD", typeof(string));
            dtWorkings.Columns.Add("passFail", typeof(int));

            dtWorkings.Rows.Add(2, "Computer systems", "P", 3);
            dtWorkings.Rows.Add(2, "Computer systems", "P", 2);
            dtWorkings.Rows.Add(3, "Web rubbish", "P", 3);

            // create the results datatable
            DataTable dtResults = new DataTable();
            dtResults.Columns.Add("units", typeof(int));
            dtResults.Columns.Add("name", typeof(string));
            dtResults.Columns.Add("P", typeof(bool));
            dtResults.Columns.Add("M", typeof(bool));
            dtResults.Columns.Add("D", typeof(bool));
            dtResults.Columns.Add("points", typeof(int));

            //fill the results table
            foreach (var units in dtWorkings.Rows.Cast().GroupBy(r => r["unitNo"]))
            {
                var p = units.Where(r => (string)r["criterionPMD"] == "P").All(r => (int)r["passFail"] == 3);
                var m = units.Where(r => (string)r["criterionPMD"] == "M").All(r => (int)r["passFail"] == 3);
                var d = units.Where(r => (string)r["criterionPMD"] == "D").All(r => (int)r["passFail"] == 3);
                dtResults.Rows.Add(
                     units.Key,//UnitNo
                     units.Select(r => r["unitName"]).First(),//UnitName                    
                     p,
                     m,
                     d,
                     p ? (m ? (d ? 90 : 80) : 70) : 0);//Points
            }

使用复杂的条件表达式,您可以确保只有满足所有,p,m和d标准时才会给出90分。

即使在仅具有通过和区分标准的单元中,这也将给出正确的结果,因此只能有90,70或0个点。不知道这是否是你的要求。

在仅有“P”标准的示例中,很难确定70或90分是否是正确的结果。此代码段检查是否满足所有P,M和D标准,并且在这种情况下即使没有M或D标准并且所有P标准都已通过,也会给出90分。我认为在你所有的现实场景中你都不会有这种优势,但无论如何都值得考虑这个问题。