了解LINQ查询和ViewModel

时间:2013-10-11 00:00:12

标签: 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 

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

我不知道

  • 当我可以直接向Controller查询我需要的数据时,为什么我需要ViewModel
  • ViewModel类实际上使用从查询中检索到的数据的内容 - 是否会对其进行过滤?从中构造一个对象?从PHP和MySQL的背景来看,会有什么比较?
  • 如何查询表中的特定列。我使用select new {},因为我认为这相当于?
  • 为什么上述LINQ语句不起作用。

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

2 个答案:

答案 0 :(得分:6)

问题1

  

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

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

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

  

欢迎, Bob 。您上次访问 2013-10-11

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

  1. 用户名
  2. 用户上次访问
  3. 因此:

    public class UserDetailsViewModel
    {
        public string FirstName { get; set; }
        public DateTime LastVisit { get; set; }
    }
    

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

    您执行此操作的原因是因为它是良好做法。但这还不够好,让我解释一下。

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

    问题2

      

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

    ViewModel是某个architectural patternsMVC等特定MVVM的原生(或至少是常见的)概念。 ViewModel并没有真正“做”任何事情。它没有任何逻辑;它没有方法。它只包含一个属性列表(和属性),用于定义使用此ViewModel的视图所需的内容。

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

    问题3

      

    如何查询表中的特定列。我使用select new {},因为我假设它是等价的?

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

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

    例如:

    var query = from user in Users
                where user.FirstName == "Bob"
                select user;
    

    问题4

      

    为什么上面的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;