我需要在View页面中加载多个实体类型。我为此目的使用ViewModel
。但是,我需要进行大约5-6个数据库调用来加载每组数据并将它们分配给ViewModel
的相关属性。我想知道这是否是一种推荐的方法,因为它需要多个数据库调用。或者,我是否过度关注这个?这是我代码的快照:
var model = new EntryListVM();
string userid = "";
if (ViewBag.CurrentUserId == null)
userid = User.Identity.GetUserId();
else
userid = ViewBag.CurrentUserId;
ViewBag.CurrentUserId = userid;
//First database call
model.DiscussionWall = db.DiscussionWalls.Find(wallId);
//Second database call to learn if the current students has any entry
model.DiscussionWall.DoesStudentHasEntry = db.Entries.Any(ent => ent.DiscussionWallId == wallId && ent.UserId == userid);
model.PageIndex = pageIndex;
//Third database call
model.TeacherBadges = db.Badges.Where(b => b.CourseId == model.DiscussionWall.CourseId && b.IsSystemBadge == false && b.IsEnabled == true).ToList();
//Fourth database call
model.Reactions = db.Reactions.Where(re => re.CourseId == model.DiscussionWall.CourseId).ToList();
int entryPageSize = Convert.ToInt32(ConfigurationManager.AppSettings["EntryPageSize"]);
int firstChildSize = Convert.ToInt32(ConfigurationManager.AppSettings["FirstChildSize"]);
List<ViewEntryRecord> entryviews = new List<ViewEntryRecord>();
bool constrainedToGroup = false;
if (!User.IsInRole("Instructor") && model.DiscussionWall.ConstrainedToGroups)
{
constrainedToGroup = true;
}
//Fifth database call USING VIEWS
//I used views here because of paginating also to bring the first
//two descendants of every entry
entryviews = db.Database.SqlQuery<ViewEntryRecord>("DECLARE @return_value int;EXEC @return_value = [dbo].[FetchMainEntries] @PageIndex = {0}, @PageSize = {1}, @DiscussionWallId = {2}, @ChildSize={3}, @UserId={4}, @ConstrainedToGroup={5};SELECT 'Return Value' = @return_value;", pageIndex, entryPageSize, wallId, firstChildSize, userid, constrainedToGroup).ToList();
model.Entries = new List<Entry>();
//THIS FUNCTION MAP entryviews to POCO classes
model.Entries = ControllerUtility.ConvertQueryResultsToEntryList(entryviews);
//Sixth database call
var user = db.Users.Single(u => u.Id == userid);
model.User = user;
我想知道这对初始页面加载是否负担过重?
我可以使用SQL-View一次读取所有数据,但我想我会得到一个太复杂的数据集来管理。
另一个选项可能是在页面加载(主数据)完成后使用Ajax加载其他结果。例如,我可以在加载页面后使用AJAX加载TeacherBadges
。
我想知道哪种策略更有效并推荐?是否存在特定策略可能更有用的特定情况?
谢谢!
答案 0 :(得分:4)
这完全取决于您的场景 - 不同的场景有不同的处理方式。做一些性质相似的事情没有一种正确的方法。什么可能对我有用可能不适合你。曾经听过这样的说法:there are many ways to kill a cat
?那肯定适用于编程。
我将根据我的想法回答。你的问题非常广泛而且不具体。
但是,我不确定这是否是推荐的方法 需要多次数据库调用。
有时您需要进行一次数据库调用来获取数据,有时您需要进行多次数据库调用才能获取数据。例如:
我正在使用ViewModel。
使用view models
查看您的观点是一件好事。如果您想了解更多关于视图模型的内容,那么您可以阅读我给出的关于该主题的答案:
当您拥有来自多个数据集的数据时,查看模型非常理想。视图模型还可用于显示来自一个数据集的数据,例如:
我在单独的linq语句中读取控制器中的数据,并且 将它们分配给ViewModel的相关List属性。
我不会总是返回一个列表 - 这完全取决于你需要什么。
如果我有一个对象要返回,那么我将填充一个对象:
User user = userRepository.GetById(userId);
如果我有一个要返回的对象列表,那么我将返回一个对象列表:
List<User> users = userRepository.GetAll();
返回单个对象然后填充此对象的列表是没有用的:
List<User> user = userRepository.GetByUserId(userId).ToList();
第二个选项可能是使用SQL-View来读取所有数据 数据库调用,然后将它们正确映射到实体 控制器。
这与您的第一个问题类似,您在数据库级别返回数据的方式取决于您。它可以是stored procedures
或views
。我个人更喜欢存储过程。我之前从未使用过视图。无论你选择什么,上面提到的存储库方法看起来都应该是一样的。
第三个选项可能是使用Ajax加载后的其他结果 页面加载(包含主数据)已完成。
如果您愿意,可以这样做。如果不是真的需要,我不会这样做。我尝试在页面加载时加载数据。我尝试在页面完全加载之前在屏幕上获取尽可能多的数据。有些时候我必须在页面加载后转到AJAX
路由。加载页面后,我不得不进行AJAX调用来加载我的HTML表格。
如果你真的需要显示数据,那就这么做。你不需要任何奇特的方法来做到这一点。也许以后你需要更改屏幕数据,然后使用AJAX很酷。
我想知道哪种策略更有效并推荐?在那儿 特定策略可能更有用的特定情况?
我们假设您要显示用户列表。我们进行数据库调用并将列表返回给视图。如果我只返回一个列表,我通常不会使用视图模型:
public class UserController : Controller
{
private IUserRepository userRepository;
private IAddressRepository addressRepository;
public UserController(IUserRepository userRepository, IAddressRepository addressRepository)
{
this.userRepository = userRepository;
this.addressRepository = addressRepository;
}
public ActionResult Index()
{
List<User> users = userRepository.GetAll();
return View(users);
}
}
您的观点可能如下所示:
@model List<YourProject.Models.User>
@if (Model.Count > 0)
{
foreach (var user in Model)
{
<div>@user.Name</div>
}
}
如果您需要获取单个用户的详细信息和地址列表,那么我将使用视图模型,因为现在我需要显示来自多个数据集的数据。因此,用户视图模型可能如下所示:
public class UserViewModel
{
public UserViewModel()
{
Addresses = new List<Address>();
}
public int Id { get; set; }
public string Name { get; set; }
public List<Address> Addresses { get; set; }
}
您的详细信息操作方法可能如下所示:
public ActionResult Details(int id)
{
User user = userRepository.GetById(id);
UserViewModel model = new UserViewModel();
model.Name = user.Name;
model.Addresses = addressRepository.GetByUserId(id);
return View(model);
}
然后您需要在视图中显示用户详细信息和地址:
@model YourProject.ViewModels.UserViewModel
<div>First Name: @Model.Name</div>
<div>
@if (Model.Addresses.Count > 0)
{
foreach (var address in Model.Address)
{
<div>@address.Line1</div>
<div>@address.Line2</div>
<div>@address.Line3</div>
<div>@address.PostalCode</div>
}
}
</div>
我希望这会有所帮助。这可能是一个广泛的答案,但它可以指导你在正确的道路上。
答案 1 :(得分:1)
对于链接数据,它很简单(你可能知道这种方式):
var users = context.Users.Include(user => user.Settings).ToList();
它会查询所有用户并为每个用户预加载设置。
以下是一个例子:
context.Users.Select(user => new
{
User = user,
Settings = context.Settings
.Where(setting => setting.UserId == user.Id)
.ToList()
}).ToList();
您仍然需要选择主要查询集合(在这种情况下为用户),但这是一个选项。希望它有所帮助。