【问题标题】:3.5 VS 4.0 .NET Framework3.5 与 4.0 .NET 框架
【发布时间】:2011-07-05 06:26:36
【问题描述】:

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

【问题讨论】:

  • 您可以选择一个元组,或者至少在 AFAIK 3.5 中选择一个动态类型。
  • 你能通过转换上面的代码给我看一个例子吗?我实际上正在决定是否转换为 4.0 或不..

标签: c# linq frameworks


【解决方案1】:

这个(在 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 会为类似的解决方案提供一些重构提示。
  • 感谢您的及时回复。但我不认为你能够以这种方式通过,因为我正在传回 IList?我在 CourseTutor.Id = ct.Id 收到此错误“无效的初始化程序成员声明器”
  • @belinq:应该可以。 from ... select 语句返回IQueryable&lt;Type&gt;,其中Type 是您在select 之后编写的任何内容的类型。所以我的建议会首先产生一个IQueryable&lt;User&gt;,在上面我们调用ToList()得到一个List&lt;User&gt;,它实现了IList&lt;User&gt;,因此可以返回。
  • @belinq:当你有一个“适合”查询结果的现有类,并且当你想从一个方法返回一个查询结果时,你应该使用select new ExistingClass{}。如果您只想在方法内部使用查询结果并且没有“适合”结果的类,则可以使用select new{}(称为匿名类型)。
  • @belinq -- 这不是垃圾,因为它很长,它是垃圾,因为您通过创建依赖项来破坏实体模型只是为了支持您的显示需求。您直观地认识到您的显示模型和实体模型是不同的 - 因此您会感到沮丧 - 但您需要通过为您的显示需求创建单独的模型来将其正式化。
【解决方案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;

希望这会有所帮助。

【讨论】:

  • 我认为保持模型中的关系是正确的做法,但这并不能真正解决问题。当您这样做时,您确实获得了课程中的所有用户,但是对于每个用户,您可以获得他们的所有课程以及他们辅导的所有课程。忽略可能没有直接的课程关系(它是通过导师、讲师或学生之一),对于每个用户,您将获得他们辅导的课程的集合,而不仅仅是所讨论的一门课程。从中找出感兴趣的课程可能是不可能的。最好为视图使用特定模型,IMO。
  • 如果您只是将数据作为只读视图返回,那么为什么不考虑使用存储过程来展平查询并在一个简单的查询中将所有数据返回给您呢?这完全取决于您的经验在哪里以及您乐于使用哪种技术。如果您决定使用存储过程,那么您有几个选择;使用实体框架(4.0 更容易)查看msdn.microsoft.com/en-us/library/bb896279.aspx 或创建一个数据集并将存储过程添加到其中。后者是一件轻而易举的事,但也许会引入其他需要维护的东西。
【解决方案3】:

我通常处理此问题的方式是为 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;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2012-06-10
    相关资源
    最近更新 更多