了解LINQ查询和ViewModel

Eam*_*onn 1 c# sql linq visual-studio asp.net-mvc-4

我有三个简单的表 - 用户组,工作人员和称呼.所有都有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 
Run Code Online (Sandbox Code Playgroud)

我有一个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; }

}
Run Code Online (Sandbox Code Playgroud)

并尝试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 };
Run Code Online (Sandbox Code Playgroud)

哪个加载到我的控制器中:

        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
            }
        );
Run Code Online (Sandbox Code Playgroud)

请注意,intellisense在子查询和主查询之间标记了相同名称的列,因此我引入了一些别名.我还希望向视图传递所有可用人员的下拉列表,因此视图模型中的列表.

我在LINQ语句中的select调用上遇到错误: Cannot implicitly convert type 'System.Linq.IQueryable<AnonymousType#4>' to '<...StaffUserGroup> An explicit conversion exists. Are you missing a cast?

我不知道

  • 当我可以直接向Controller查询我需要的数据时,为什么需要ViewModel
  • 然后ViewModel类实际上从查询中检索的数据做了什么 - 它是否过滤了它?从中构造一个对象?从我在PHP和MySQL的背景下,将会有什么比较?
  • 如何从表中查询特定列.我用select new {},因为我假设这相当于?
  • 为什么上面的LINQ语句不起作用.

如果需要,我可以发布模型,视图或控制器.非常感谢任何帮助和建议!

Row*_*man 6

问题1

当我可以直接向Controller查询我需要的数据时,为什么需要ViewModel

ViewModel是您编写的POCO,它可以准确定义视图所需的内容,以便正确显示自身.

例如,假设您有一个欢迎用户的页面(视图).

欢迎,鲍勃.您的上次访问是2013-10-11.

ViewModel是一个简单的类,它完全定义了视图所需的内容.

  1. 用户的名字
  2. 用户上次访问

因此:

public class UserDetailsViewModel
{
    public string FirstName { get; set; }
    public DateTime LastVisit { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

(通常)控制器负责创建ViewModel,确保它已填充,将其提供给视图并最终返回视图.控制器没有做太多其他事情; 它的职责是有限的,行动中的代码应该相当小.

你这样做的原因是因为这是一个很好的做法.但这还不够好,让我解释一下.

可以简单地运行查询,返回某个域对象的IEnumerable(例如用户列表)并将其提供给视图.这是在许多MVC演示中完成的.问题是它非常有限/限制.如果要更改以后显示的视图会发生什么?如果域模型略有变化会发生什么?当整齐有序且关注点分离时,管理和更改事物会更容易.

问题2

然后ViewModel类实际上对从查询中检索的数据做了什么 - 它是否过滤了它?从中构造一个对象?从我在PHP和MySQL的背景下,将会有什么比较?

ViewModel是某些体系结构(或至少是常见的)某些体系结构模式(如MVCMVVM)的概念.ViewModel并没有真正"做"任何事情.它没有任何逻辑; 它没有方法.它只包含一个属性列表(和属性),用于定义使用此ViewModel的视图所需的内容.

由于ViewModel不是特定于.NET,因此没有完全相同的PHP.它只是一个与MVC,MVVM等相关的概念.PHP等价物将是PHP MVC ViewModel.请记住,ASP.NET MVC只是MVC模式的一个实现.PHP有自己的MVC实现.

问题3

如何从表中查询特定列.我使用select new {},因为我认为这相当于?

这取决于你是如何做到的.EntityFramework是一个对象关系映射器,通常用于ASP.NET MVC应用程序.这样,您就不会直接查询底层存储或列.相反,EF会将表和列映射到.NET对象,然后操纵它们.

我建议你尽量处理对象,而不是在你去的时候创建匿名类型并试图抓住特定的列.请记住,LINQ不是SQL.方法不应该是"查询这个表,抓住这些列,这个子句的位置",而应该是"从这组对象中,抓住这里的对象,这个子句在哪里".

例如:

var query = from user in Users
            where user.FirstName == "Bob"
            select user;
Run Code Online (Sandbox Code Playgroud)

问题4

为什么上面的LINQ语句不起作用.

正如描述所说,你试图给一个IEnumerable的StaffUserGroup一个IEnumerable的匿名.我相信这是因为你选择的东西是为了填充你的ViewModel.如果不了解事物的结构,很难修复代码.我在这里的建议是看看其他人是如何在MVC中进行LINQ/EntityFramework的.它只需要一些练习,直到你对事情的运作方式感到满意.