1

我正在学习 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();
        }
    } 

但是,我仍然不明白如何获取旅程详细信息。My User 和 Journey 实体在多对多关系方面是正确的。下面是具有新存储库方法的控制器。

        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
}
4

2 回答 2

2

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

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>但是这不适用于您的存储库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();
    }
} 

但是,这可能是表示层和数据层的不可接受的混合,具体取决于您的体系结构的严格程度。

于 2013-08-25T14:05:52.257 回答
1

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

考虑 和 之间的关系UserJourney您应该决定哪个实体拥有该关系并用于Aggregate Root获取数据。

什么是聚合Aggregate Root会有帮助的。

更新:

实体

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 
    }
}

视图模型

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.  
}
于 2013-08-23T15:50:39.087 回答