我有三个简单的表 - 用户组,员工和称呼。所有都有ID,名称/描述和活动列。还为用户组分配了可选的员工ID,并为员工分配了非可选的称呼ID。我希望查询这些表,以返回所有活动用户组的完整列表,以及相关的工作人员(是任何),以及他们的相关的称呼。
正在运行的SQL查询如下:
SELECT grp.ID, grp.Desc, grp.Active, sub.Name, sub.Desc
FROM Tbl_UserGroup AS grp
LEFT JOIN (
SELECT st.ID, st.Name, sal.Desc
FROM PrmTbl_Staff AS st
LEFT JOIN PrmTbl_Salutation AS sal ON st.SalutationID = sal.ID
WHERE 1
) AS sub ON grp.StaffID = sub.ID
WHERE grp.Active = TRUE
ORDER BY grp.ID DESC
我有一个ViewModel,如下所示:
public class StaffUserGroup
{
public int GroupID { get; set; }
public string GroupDesc { get; set; }
public bool GroupActive { get; set; }
public int? StaffID { get; set; }
public string StaffName { get; set; }
public string SalutationName { get; set; }
public List<PrmTbl_Staff> StaffsList { get; set; }
}
尝试LINQ查询:
IEnumerable<Tbl_UserGroup> grpsQuery;
grpsQuery = from grp in db.Tbl_UserGroups
join sub in(
from st in db.PrmTbl_Staffs
join sal in db.PrmTbl_Salutations on st.SalutationID equals sal.ID
select new { StID = st.ID, st.Name, Salt = sal.Desc }
) on grp.StaffID equals sub.StID
where grp.Active = true
orderby grp.ID descending
select new { grp.ID, grp.Desc, grp.Active, sub.Name, sub.Salt, sub.StID };
我的控制器中加载了哪个:
var viewModel = grpsQuery.Select(group =>
new StaffUserGroup
{
GroupID = group.GroupID,
GroupDesc = group.GroupDesc,
GroupActive = group.GroupActive,
StaffID = group.StaffID,
StaffName = group.StaffName,
SalutationName = group.SalutationName,
StaffsList = rtrnStaff
}
);
请注意,intellisense在子查询和主查询之间标记了相同名称的列,因此我引入了一些别名。我还希望向视图传递所有可用人员的下拉列表,因此视图模型中的列表。
我在LINQ语句中的select调用上遇到错误:Cannot implicitly convert type 'System.Linq.IQueryable<AnonymousType#4>' to '<...StaffUserGroup> An explicit conversion exists. Are you missing a cast?
我不知道
select new {}
,因为我认为这相当于?如果需要,我可以发布模型,视图或控制器。非常感谢任何帮助和建议!
答案 0 :(得分:6)
当我可以直接向Controller查询我需要的数据时,为什么我需要ViewModel
ViewModel是您编写的POCO,它可以准确定义视图所需的内容,以便正确显示自己。
例如,假设您有一个欢迎用户的页面(视图)。
欢迎, Bob 。您上次访问 2013-10-11 。
ViewModel是一个简单的类,它完全定义了视图所需的内容。
因此:
public class UserDetailsViewModel
{
public string FirstName { get; set; }
public DateTime LastVisit { get; set; }
}
(通常)控制器负责创建ViewModel,确保它已填充,将其提供给视图并最终返回视图。控制器没有做太多其他事情;它的职责是有限的,行动中的代码应该相当小。
您执行此操作的原因是因为它是良好做法。但这还不够好,让我解释一下。
可以简单地运行查询,返回某个域对象的IEnumerable(例如用户列表)并将其提供给视图。这是在许多MVC演示中完成的。问题是它非常有限/限制。如果要更改以后显示的视图会发生什么?如果域模型略有变化会发生什么?当整齐有序并且问题分离时,管理和改变事物会更容易。
ViewModel类实际上对从查询中检索的数据做了什么 - 它是否过滤了它?从中构造一个对象?从PHP和MySQL的背景来看,会有什么比较?
ViewModel是某个architectural patterns和MVC等特定MVVM的原生(或至少是常见的)概念。 ViewModel并没有真正“做”任何事情。它没有任何逻辑;它没有方法。它只包含一个属性列表(和属性),用于定义使用此ViewModel的视图所需的内容。
没有完全相同的PHP,因为ViewModel不是特定于.NET的。它只是一个与MVC,MVVM等相关的概念。 PHP等价物将是PHP MVC ViewModel。请记住,ASP.NET MVC只是MVC模式的一个实现。 PHP有自己的MVC实现。
如何查询表中的特定列。我使用select new {},因为我假设它是等价的?
这取决于你是怎么做的。 EntityFramework是一个对象关系映射器,通常用于ASP.NET MVC应用程序。这样,您就不会直接查询底层存储或列。相反,EF会将表和列映射到.NET对象,然后操纵它们。
我建议你尽量处理对象,而不是在你去的时候创建匿名类型并试图抓住特定的列。请记住LINQ isn't SQL。方法不应该是“查询这个表,抓住这些列,这个子句的位置”,而应该是“从这组对象中,抓住这里的对象,这个子句在哪里”。
例如:
var query = from user in Users
where user.FirstName == "Bob"
select user;
为什么上面的LINQ语句不起作用。
正如描述所说,你试图给一个IEnumerable的StaffUserGroup一个IEnumerable的Anonymous。我相信这是因为你选择的东西是为了填充你的ViewModel。如果不了解事物的结构,很难修复代码。我的推荐是look at how some other people are doing LINQ/EntityFramework in MVC。只需要做一些练习,直到你对事情的运作方式感到满意为止。
答案 1 :(得分:0)
看来你可能正在尝试放置新类型的物品
select new { grp.ID, grp.Desc, grp.Active, sub.Name, sub.Salt, sub.St }
到用于
类型的项目的集合中
IEnumerable<Tbl_UserGroup> grpsQuery;