如何集成查询存储库中多个实体并将数据发送到View的Linq-to-Entity查询
本文关键字:查询 数据 Linq-to-Entity View 实体 集成 何集成 存储 | 更新日期: 2023-09-27 18:28:51
我正在学习MVC、存储库模式和EF,我需要一些关于如何最好地将包含查询多个实体的查询的方法集成到存储库中的建议。
目前,我已经创建了一个存储库类,它实现了一个接口,并使用DbContext的实例使用实体框架从数据库中检索数据,但只针对一个实体。
已编辑。。。我的存储库中有GetJourneys()方法,但我不确定如何从Controller中的查询中获取Journey详细信息。我可以获取用户详细信息。
public IEnumerable<User> GetJourneys()
{
var todayDate = DateTime.Now;
//Woking with many to many Relationship
//(join tables) in Asp.net MVC/Entity Framework
var viewModel = from j in dbContext.Users
from u in dbContext.Journeys
where u.DepartDate >= todayDate.Date
orderby u.DepartDate ascending
select j;
return viewModel.ToList();
}
下面是我的用户实体
public class User
{
[Key, Required]
public int UserID { get; set; }
[MaxLength(30), Required]
public string FirstName { get; set; }
[MaxLength(30), Required]
public string LastName { get; set; }
[Required]
public string ProfileImg { get; set; }
[MaxLength(30), Required]
public string FbLink { get; set; }
public ICollection<Journey> Journeys { get; set; }
}
下面是我的控制器
public ViewResult Search()
{
var userJourneyList = from user in repository.GetJourneys() select user;
var searchView = new List<SearchViewModel>();
try
{
if (userJourneyList.Any())
{
foreach (var user in userJourneyList)
{
searchView.Add(new SearchViewModel()
{
//JourneyDestination = user.Journeys.FromDestination,
//JourneyDate = user.Journeys.DepartDate,
UserName = user.FirstName,
ProfileImage = user.ProfileImg,
//SeatsAvailable = user.Journeys.SeatsAvailable,
//UserType = user.Journeys.UserType
});
}
returnAmount = 1;
ViewBag.Amount = returnAmount;
}
else
{
returnAmount = 0;
ViewBag.Amount = returnAmount;
}
var todayDate = DateTime.Now;
}
catch (NullReferenceException ex)
{
MessageBox.Show(ex.Message);
}
return View(searchView.ToList());
}
更新现在在我的存储库中
public IList<User> GetAllUsersWithJourneys()
{
using (var db = new EfDbContext())
{
var users = from userJourney in db.Users.Include(i => i.Journeys)
select userJourney;
return users.ToList();
}
}
然而,我仍然不知道如何获得旅程的详细信息。"我的用户"answers"旅程"实体在多对多关系方面是正确的。下面是具有新存储库方法的控制器。
var userJourney = repository.GetAllUsersWithJourneys();
var searchView = new List<SearchViewModel>();
try
{
if (userJourneyList.Any())
{
foreach (var user in userJourney)
{
searchView.Add(new SearchViewModel()
{
UserName = user.FirstName,
JourneyDestination = user.Journeys.ToDestination //ERROR
});
}
}
else
{
//user will be notified that no results were found and that they are given the option to create the journey that they seek
returnAmount = 0;
ViewBag.Amount = returnAmount;
}
}
catch (NullReferenceException ex)
{
MessageBox.Show(ex.Message);
}
return View(searchView.ToList());
我的ViewModel看起来像这个
public class SearchViewModel
{
public string ProfileImage { get; set; } //User
public string JourneyDestination { get; set; } //Journey
public DateTime JourneyDate { get; set; } //Journey
public string UserName { get; set; } //User
public int SeatsAvailable { get; set; } //Journey
public bool UserType { get; set; } //Journey
}
如果您要做的是将所有用户旅程扁平化为一个列表(假设基于您传递给视图的模型的形状),那么有一种方法是这样的:
var userJourney = repository.GetAllUsersWithJourneys();
var searchView = new List<SearchViewModel>();
try
{
if (userJourneyList.Any())
{
foreach (var user in userJourney)
{
foreach(var journey in user.Journeys)
{
searchView.Add(new SearchViewModel()
{
UserName = user.FirstName,
JourneyDestination = journey.JourneyDestination
});
}
}
}
}
catch (NullReferenceException ex)
{
// ...
}
或者,您可以对其进行重构,使其功能更强大:
var userJourney = repository.GetAllUsersWithJourneys();
var searchView = userJourney.SelectMany(
user => user.Journeys.Select(
journey => new SearchViewModel()
{
UserName = user.FirstName,
JourneyDestination = journey.JourneyDestination
}
)
)
.ToList();
if (!searchView.Any())
{
// no results logic
}
如果您的存储库返回IQueryable<User>
,而不是调用ToList()
并返回IList<User>
,则第二种方法会更好,BUT这将无法在存储库立即处理DbContext
的情况下工作。按照目前的情况(使用ToList()
),您最终将在内存中执行比让SQL执行更多的处理。如果您的存储库知道SearchViewModel
,您可以这样做:
public IList<SearchViewModel> GetSearchViewModels()
{
using (var db = new EfDbContext())
{
var users = from user in db.Users
from journey in user.Journeys
select new SearchViewModel()
{
UserName = user.FirstName,
JourneyDestination = journey.JourneyDestination
}
select userJourney;
return users.ToList();
}
}
然而,这可能是不可接受的表示层和数据层的混合,这取决于您的体系结构有多严格。
如何最好地将包含查询多个实体的查询的方法集成到存储库中。
考虑到User
和Journey
之间的关系,您应该决定哪个实体拥有该关系,并使用Aggregate Root
来获取数据。
Aggregate Root
在What';是聚合根吗?会很有帮助。
更新:
实体
public class User
{
public User()
{
this.Journeys = new List<Journey>();
}
public int Id { get; set; }
public virtual IList<Journey> Journeys { get; set; }
}
public class Journey
{
public Journey()
{
this.Users = new List<User>();
}
public int Id { get; set; }
public virtual IList<User> Users { get; set; }
}
重新定位
public class UserRepository
{
public IList<User> GetAllUsersWithJourneys()
{
//Fetch all Users; Include Journeys
}
}
public class JourneyRepository
{
public IList<Journey> GetAllJourneysWithUsers()
{
//Fetch all journeys; Include Users
}
}
ViewModel
public class UserJourneyViewModel
{
public int UserId { get; set; }
public int JourneyId { get; set; }
}
控制器动作
public ViewResult Search()
{
// Use UserRepository or JourneyRepository to make a list of
// UserJourneyViewModel that provides appropriate data for the view.
}