[英]How do I return a Model from Entity Framework (Database First) that includes the Navigation Properties after the context is disposed?
What I am asking is actually a little more broad than the question title...but that is kind of the specific question. 实际上,我要问的内容比问题标题要宽得多……但这是一个特定的问题。
I am trying to thin out my controllers and move all business logic / interaction with Entity Framework into a Service Layer so that my controllers don't need the context at all, which I believe is the "right" way to do things. 我正在尝试精简控制器,并将与Entity Framework的所有业务逻辑/交互都移入服务层,以使控制器根本不需要上下文,我认为这是做事的“正确”方法。
The problem is that when I create a Service Layer method that returns a domain model, it does not contain the Navigation Properties and once I am calling this method in my controller and need to access these navigation properties, the context has already been disposed. 问题在于,当我创建一个返回域模型的服务层方法时,它不包含导航属性,并且一旦我在控制器中调用此方法并需要访问这些导航属性,就已经处理了上下文。 This then forces me to make multiple calls out to other Service Layer methods to get the rest of the properties I need so that I can create my View Model.
然后,这迫使我对其他服务层方法进行多次调用,以获取所需的其余属性,以便可以创建视图模型。
I'm sure the issue is that I am not creating my methods in the proper way or missing some component of the correct architecture for this situation so here is some code to demonstrate what I am doing. 我确定问题是我没有以正确的方式创建我的方法,或者缺少针对这种情况的正确体系结构的某些组件,因此这里有一些代码来演示我在做什么。
Service Layer method: 服务层方法:
public IEnumerable<Paper> GetPapersForReview(int userID, string courseID, string role)
{
using (USGEntities context = new USGEntities())
{
IEnumerable<Paper> models = (from a in context.Papers
join b in context.Users_Roles on a.Paper_Types.Course_ID equals b.Course_ID
where a.Status == "REV" && a.Deleted == false && b.User_ID == userID && b.Role.Name == role && b.Course_ID == courseID
select a).ToList();
return models;
}
}
Controller method: 控制器方式:
public JsonResult GetPapersForReview(string courseID)
{
int user_id = new User().GetUserIDByDomainAccount(User.Identity.Name);
var vm = (from a in new PaperService().GetPapersForReview(user_id, courseID, "Reviewer")
select new PaperViewModel()
{
Paper_ID = a.ID,
Proposal_ID = a.Proposal_ID,
Expected_Start_Date = a.Expected_Start_Date
}).Distinct().ToList();
foreach (var paper in vm)
{
Proposal proposal = new ProposalService().GetProposal(paper.Proposal_ID);
Paper_Types paper_type = new PaperTypeService().GetPaperTypeByPaper(paper.Paper_ID);
paper.Paper_Type = paper_type.Description;
paper.Resources = new PaperService().GetResourceList(paper.Paper_ID);
paper.Proposal_Title = proposal.Title;
paper.Author = new UserService().GetNameByUserID(proposal.Author_User_ID);
}
return Json(vm, JsonRequestBehavior.AllowGet);
}
So you can see after I make the call to the Service Layer method and get the properties that I have direct access to, I then have to loop back through that and make additional calls to get the rest of the properties that I need. 因此,您可以在调用Service Layer方法并获得可以直接访问的属性后看到,然后我必须循环遍历该过程,并进行其他调用以获取我需要的其余属性。 I know this is not the right way to do things.
我知道这不是正确的做事方式。 So how do I structure things better to return everything I need from the Service Layer?
那么,如何更好地构造事物以从服务层返回我需要的一切呢?
Some other related questions are: should I be returning IEnumerables or something else from the Service Layer and do I need to be calling ToList() in both places? 其他一些相关的问题是:我应该从服务层返回IEnumerables还是其他东西,是否需要在两个地方都调用ToList()?
You have the .Include
extension: 您具有
.Include
扩展名:
public IEnumerable<Paper> GetPapersForReview(int userID, string courseID, string role)
{
using (USGEntities context = new USGEntities())
{
var result = context.Papers
.Include(paper => paper.User)
.Where(paper => paper.Status == "REV" && paper.Deleted == false && paper.User_ID == userID && paper.User.Role.Name == role && paper.Course_ID == courseID)
.ToList();
return result;
}
}
You can even use .ThenInclude
if you have multiple levels: 您甚至可以使用
.ThenInclude
如果您具有多个级别):
.Include(p => p.Item)
.ThenInclude(p => p.SubItem)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.