通过一个方法得到一个学生名单A,有学号姓名等通过另外一个方法,得到一部分学生的学号和成绩B。现在要得到一个通过第一个方法得到的学生名单和他们的成绩,如果没有成绩的就为空或者0====我的做法是 从学生派生一个有成绩的学生实体,加一个成绩字段
并new出一个集合C。遍历学生名单A,反射属性,给新派生的学生实体赋值,并查询B集合,给成绩赋值====
看着满简单的需求,写的太复杂,有没有更简单的方法呢?

解决方案 »

  1.   

    不太明白楼主的意思,我怎么感觉只要Left Join一下就可以了啊,哪里要反射这么复杂。
      

  2.   

    这不就是典型的联合查询嘛...Linq当然也支持...
      

  3.   

    看具体情况,有时可以用stream直接copy一块内存过去
      

  4.   

    "遍历学生名单A,反射属性",我不明白你为什么要反射属性,而不能直接使用属性,难道说是类似DataTable一样的弱类型吗?如果真是在使用弱类型,不如直接用DataTable呢,或者提供类似DataTable那样的访问方式。
      

  5.   

    up,其实就是两个集合的联合查询然后select一个匿名类型集合嘛
      

  6.   

    学生名单和成绩不是同一个地方的,不同的数据库,而且去到的已经是个集合了,不能用数据库的join
      

  7.   

    不能在Queryable里Join,那就在Enumerable里Join啊。
      

  8.   

    Linq2Object 不一定非要在DB里join。而且你这个场景,我觉得linq是最好的选择
      

  9.   

    似乎可以用join,但如果那个成绩也是一个集合,有 [语文:90], [数学:70], [英语:80],通过学号关联,返回的成绩是个集合类型,是不是很麻烦?
      

  10.   

    有点复杂,sql中表关联一下就行了吧
      

  11.   


    var query = from a in list1 join b in list2 on a.Id equals b.Id
                select new Student { a.Id, a.Name, b.Score1 };这点代码量还是要比反射强多了吧。
      

  12.   

    大概就是这个意思吧:    public class Student
        {
            public string StuNo { get; set; }
            public string Name { get; set; }
        }    public class Score
        {
            public string StuNo { get; set; }
            public List<int> Scores { get; set; }
        }            List<Student> listStu = new List<Student> 
                {
                    new Student{ StuNo="001", Name="A"},
                    new Student{ StuNo="002", Name="B"},
                    new Student{ StuNo="003", Name="C"},
                    new Student{ StuNo="004", Name="D"},
                };            List<Score> listScore = new List<Score> 
                {
                    new Score{StuNo="001", Scores=new List<int>{94,92,95,90}},
                    new Score{StuNo="002", Scores=new List<int>{66,77,88,99}},
                    new Score{StuNo="004", Scores=new List<int>{78,87,65,77}}
                };            var query = from stu in listStu
                            join score in listScore on stu.StuNo equals score.StuNo into group1
                            from result in group1.DefaultIfEmpty()
                            select new { stu.StuNo, stu.Name, Scores = result == null ? new List<int>() : result.Scores };
                foreach (var stu in query)
                    Console.WriteLine("{0} {1} {2}", stu.StuNo, stu.Name, string.Join(",", stu.Scores.ToArray()));
      

  13.   


    要把集合里的元素变成类的属性吗,行转列,在Linq To SQL里可能复杂,但在Linq To Object里应该不会太复杂吧。如果返回的结果仅仅用于做数据绑定,可以用ICustomTypeDescriptor来实现。
      

  14.   

    OJ兄怎么不当斑竹了啊?
    不过话说回来,楼主的表述上说要对学生名单A,反射属性,而你给的Linq是在知道学生名单A类型的情况下,无需反射的情况下使用的。我一直不明白为啥这个给定学生名单A不能是具体的类型。
      

  15.   

    这个学生名单倒是可以确定属性的,只是这个取得的学生名单有很多信息,比如姓名,年级,班级等等。如果用linq的话,就要都复制一次,但这个学生增加属性的话,用到linq的地方都要修改了,所以我一开始是想直接拷贝过去,不用每个属性每个属性赋值
      

  16.   

    是要Left Join应该可以List<Student> .ConvertAll<Score>(st => {
       //去成绩列表里找这个学生,若找到则给分
       var findS = List<Score> .Where(s=> s.No == st.No).SingleOrDefault();   
       st.score = findS == null ? 0 : findS.score;
       return st as Score;
    });
      

  17.   


    这就是你设计的取舍了。反射的确能减少这样的变更风险。(这种反射的性能也不会有很大的损失)
    写个通用的属性拷贝方法。反射出GetMethod()和SetMethod(),用Delegate.CreateDelegate方式创建
    属性取值和赋值的delegate,性价比还是比较高的。
      

  18.   


    转化思考下下吗!
    var newObjs =
        from 学生 in A
        join 成绩 in B on A.学好 equals B.序号 into AB
        from 综合 in AB.DefaultIfEmpty()
        select 综合;