3.5与4.0 .NET Framework的区别

3

有5个框架,不在数据库中使用关系外键,我想知道4.0如何改进这段代码垃圾,我需要在多个表连接后返回多个对象。

  public IList<User> GetTutorByCourseId(int courseId)
    {
        IList<User> output = new List<User>();
        using (leDataContext db = new leDataContext())
        {
            try
            {
                var m = from c in db.Courses
                        join ct in db.CourseByTutors on c.Id equals ct.CourseId
                        join u in db.Users on ct.TutorId equals u.Id
                        where c.Id == courseId
                        select new
                        {
                            c, ct, u
                        };

                foreach (var result in m)
                {
                    User user = new User();
                    user.Id = result.u.Id;
                    user.Name = result.u.Name;
                    user.CourseTutor.Id = result.ct.Id;
                    user.Course.Name = result.c.Name;    
                    output.Add(user);
                }
                return output;
            }
            catch (Exception ex)
            {
                Logger.Error(typeof(User), ex.ToString());
                throw;
            }
        }
    }

在GUI中有3个对象被返回给调用者。但是,为了做到这一点,我必须在User类中添加public CourseByTutors{get;set;}和public Course(get;set;)属性,但我发现这会破坏我的代码。在这种情况下,4.0版本如何解决这个问题?我读到了一些关于select tupel的内容..??


你可以选择一个元组,或者至少在3.5中使用动态类型,据我所知。 - Grant Thomas
你能否通过将我上面的代码转换成示例来展示给我看吗?我正在决定是否要转换到4.0。 - VeecoTech
3个回答

3
这个(在3.5中)怎么样?
select new User
{
    Id = u.Id,
    Name = u.Name,
    CourseTutor = new CourseTutor {Id = ct.Id},
    Course = new Course {Name = c.Name}
};
return m.ToList();

编辑:替换了非法的CourseTutor.NameCourse.Id初始化程序。假设User的构造函数没有对CourseTutorCourse进行任何复杂的初始化,那么更正后的代码将可以工作。


1
顺便提一下,ReSharper会提供一些重构提示,以寻找类似的解决方案。 - TrueWill
2
@belinq:应该可以运行。from ... select 语句返回一个 IQueryable<Type>,其中 Type 是你在 select 后面写的任何类型。所以我的建议首先会产生一个 IQueryable<User>,我们在其上调用 ToList() 来获得一个 List<User>,它实现了 IList<User>,因此可以被返回。 - Aasmund Eldhuset
嗨,我实际上很想知道4.0如何缩短那一堆代码。如果我甚至不必在“User”类中添加额外的属性,那就太好了。 - VeecoTech
1
@belinq:当您有一个现有的类与查询结果“匹配”并且想要从方法中返回查询结果时,应使用select new ExistingClass{}。如果您只想在方法内部使用查询结果,并且没有一个“匹配”结果的类,您可以使用select new{}(它被称为_匿名类型_)。 - Aasmund Eldhuset
2
@belinq -- 这不是因为它很长就是垃圾,而是因为你仅仅为了支持显示需求而创建依赖项,从而破坏了实体模型。你直觉地意识到你的显示和实体模型是不同的 -- 因此你感到沮丧 -- 但你需要迈出下一步,通过创建独立的显示模型来正式化这一点。 - tvanfosson
显示剩余10条评论

2
即使数据库中没有外键,您也可以将关系添加到EF模型中。这将有助于简化问题,因为您不必生成其他属性来存储子值;例如CourseTutor、CourseName等等。
无论是3.5还是4.0都可以帮助解决这个问题,但根据我的经验,4.0更容易实现。
一旦完成,您的代码可能如下所示:
var results = (from u in db.Users
        where u.Course.Id == courseId
        select u).ToList();
return results;

希望这能帮到你。

我认为在数据模型中保留关系是正确的做法,但这并不能真正解决问题。当您这样做时,您会获得课程中的所有用户,但对于每个用户,您都会获取他们所有的课程和所有指导的课程。忽略了可能没有直接的课程关系(它通过导师、讲师或学生之一),对于每个用户,您将获得他们指导的课程集合,而不仅仅是所讨论的那门课程。从中找出感兴趣的课程可能是不可能的。我认为最好使用特定的视图模型。 - tvanfosson
如果您只是返回数据作为只读视图,那么为什么不考虑使用存储过程来展开查询并在一个简单的查询中返回所有数据呢?这完全取决于您的经验和您喜欢使用的技术。如果您决定使用存储过程,则有几个选项;使用实体框架(4.0更容易),请查看http://msdn.microsoft.com/en-us/library/bb896279.aspx或创建数据集并将存储过程添加到其中。后者很容易做到,但可能会引入其他需要维护的内容。 - dubs

0
我通常处理这个问题的方式是为GUI创建一个单独的模型,该模型包含GUI所需的信息,与我的数据实体模型分开。如果您愿意,您可以在3.5中这样做。
public class TutorViewModel
{
     public IEnumerable<User> Tutors { get; set; }
     // the pair CourseId, UserId is the relation in CourseTutors so we only
     // need to keep it once, not once per user.
     public int CourseId { get; set; } 
     public string CourseName { get; set; }
}



public TutorViewModel GetTutorByCourseId(int courseId)
{
    var model = new TutorViewModel { CourseId = courseId };

    using (leDataContext db = new leDataContext())
    {
        try
        {
            model.CourseName = db.Courses
                                 .First( c => c.CourseId == courseId )
                                 .Name;
            model.Users = db.CourseByTutors
                            .Where( c => c.Id == courseId )
                            .Join( db.Users,
                                   c => c.TutorId,
                                   u => u.Id,
                                   (c,u) => u );

            return model;
        }
        catch (Exception ex)
        {
            Logger.Error(typeof(User), ex.ToString());
            throw;
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接