如何集成查询存储库中多个实体并将数据发送到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
}

如何集成查询存储库中多个实体并将数据发送到View的Linq-to-Entity查询

如果您要做的是将所有用户旅程扁平化为一个列表(假设基于您传递给视图的模型的形状),那么有一种方法是这样的:

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();
    }
} 

然而,这可能是不可接受的表示层和数据层的混合,这取决于您的体系结构有多严格。

如何最好地将包含查询多个实体的查询的方法集成到存储库中。

考虑到UserJourney之间的关系,您应该决定哪个实体拥有该关系,并使用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.  
}