C# 3.5与4.0.NET框架
5框架,不在数据库中使用关系外键,我想知道4.0如何改进这种垃圾代码,我需要在多个表联接后将多个对象传回C# 3.5与4.0.NET框架,c#,linq,frameworks,C#,Linq,Frameworks,5框架,不在数据库中使用关系外键,我想知道4.0如何改进这种垃圾代码,我需要在多个表联接后将多个对象传回 public IList<User> GetTutorByCourseId(int courseId) { IList<User> output = new List<User>(); using (leDataContext db = new leDataContext()) {
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;
}
}
}
public IList GetTutorByCourseId(int-courseId)
{
IList输出=新列表();
使用(leDataContext db=new leDataContext())
{
尝试
{
var m=以分贝计算的c
在c上的db.CourseByTutors中加入ct。Id等于ct.CourseId
加入db。ct.TutorId上的用户等于u.Id
其中c.Id==courseId
选择新的
{
c、 ct,u
};
foreach(var结果以m为单位)
{
用户=新用户();
user.Id=result.u.Id;
user.Name=result.u.Name;
user.CourseTutor.Id=result.ct.Id;
user.Course.Name=result.c.Name;
输出。添加(用户);
}
返回输出;
}
捕获(例外情况除外)
{
Logger.Error(typeof(User),例如ToString());
投掷;
}
}
}
GUI中有3个对象返回给调用者。然而,要做到这一点,我必须在用户类中添加public CourseByTutors{get;set}的属性和public Course(get;set;)属性,我发现这会弄乱我的代码。在这种情况下,4.0如何解决这个问题?我读了一些关于select tupel的文章 这个呢(在3.5中)
编辑:替换非法的
CourseTutor.Name
和Course.Id
初始值设定项。假设User
的构造函数没有对CourseTutor
和CourseTutor
进行任何奇特的初始化,那么更正后的代码就可以工作了。我通常处理这个问题的方法是,为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;
}
}
}
公共类TutorViewModel
{
公共IEnumerable导师{get;set;}
//CourseId和UserId对是CourseTutors中的关系,因此我们仅
//需要保存一次,而不是每个用户保存一次。
public int CourseId{get;set;}
公共字符串CourseName{get;set;}
}
公共教程视图模型GetTutorByCourseId(int-courseId)
{
var模型=新的TutorViewModel{CourseId=CourseId};
使用(leDataContext db=new leDataContext())
{
尝试
{
model.CourseName=db.CourseName
.First(c=>c.CourseId==CourseId)
名称
model.Users=db.CourseByTutors
.Where(c=>c.Id==courseId)
.Join(数据库用户,
c=>c.tutoroid,
u=>u.Id,
(c,u)=>u);
收益模型;
}
捕获(例外情况除外)
{
Logger.Error(typeof(User),例如ToString());
投掷;
}
}
}
即使数据库中没有外键,也没有理由不能将关系添加到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;
希望这有帮助。您可以选择一个元组,或者至少是3.5版本中的动态类型。您能通过转换上面的代码给我看一个例子吗?实际上,我正在决定是否转换为4.0….+1。顺便说一句,ReSharper将为类似的解决方案提供一些重构提示。感谢您的及时回复。但我不认为你能通过这种方式,因为我是通过了IList?我在CourseTutor.Id=ct上遇到了这个错误“无效的初始化器成员声明器”。Id@belinq:它应该能工作。来自。。。select语句返回一个
IQueryable
,其中Type
是在select
之后所写内容的类型。因此,我的建议将首先生成一个IQueryable
,我们在其上调用ToList()
,以获得一个列表
,该列表实现了IList
,因此可以返回。@belinq:当您有一个“适合”查询结果的现有类时,您应该使用选择新的现有类{}
,以及当您希望从方法返回查询结果时。如果您只想在方法内部使用查询结果,而没有“适合”结果的类,则可以使用select new{}
(它被称为匿名类型)。@belinq——它不是垃圾,因为它很长,而是垃圾,因为您创建依赖项只是为了支持显示需要,从而破坏了实体模型。您直观地认识到您的显示模型和实体模型是不同的——因此您感到沮丧——但您需要采取下一步的形式化步骤,为您的显示需求创建单独的模型。我认为在模型中保留关系是正确的做法,但这并不能真正解决问题。当你这样做时,你会得到课程中的所有用户,但对于每个用户,你会得到他们的所有课程和他们辅导的所有课程。忽略可能没有直接的课程关系(通过导师、讲师或学生之一),对于每个用户,您将获得他们指导的课程集合,而不仅仅是有问题的一门课程。从这一点上找出哪个课程是有意义的可能是不可能的。最好对视图使用特定的模型,IMO。如果您只是以只读方式返回数据
var results = (from u in db.Users
where u.Course.Id == courseId
select u).ToList();
return results;