1

我正在尝试跟上 MVC、linq、razor 等的速度。有些事情正在发挥作用,而另一些事情我只是遇到了死胡同,这让我很沮丧。这是我第一次无法解决。在问这个问题之前,我已经研究了所有可能的线索,这是我的第一个问题,所以请放轻松。我确信答案就在我面前,但我就是看不到。我可以输入我尝试过的 14 页内容,但我试图保持简洁明了。我已经完全破坏了我的代码,所以我从内存中提取了大部分内容,因此,标点符号错误并不是那么重要。我很抱歉错误代码不准确,因为我也从内存中提取了这些错误代码。

我的 ActionResult 中有这个左连接 linq 查询:

public ActionResult Index()
{
    var orders = from o in db.Orders
    join u in db.Users on o.UserId equals u.Id into ou
    where o.UserId == uId
    from o in ou.DefaultIfEmpty()
    select o;

    Return View(orders.ToList());
}

在 Index.cshtml 中,我通过以下方式调用结果:

@foreach (var item in Model.Orders) {
@item.User.Name //(joined Users table)
@item.OrderNumber //(Orders table)

到目前为止,一切都很好。但是,我想在索引页面上显示的不仅仅是这个列表。因此,据我所知,我需要一个 ViewModel 来在同一页面上显示其他几条数据(OrdersTotal 等)。但是,当我将上面的 linq 查询粘贴到我的模型中时:

public  List<Order> GetOrders()
    {

        var orders = from o in db.Orders
    join u in db.Users on o.UserId equals u.Id into ou
    where o.UserId == uId
    from o in ou.DefaultIfEmpty()
    select o;

        return orders.ToList();
    }

它不识别加入的用户表,这意味着它不知道 cshtml 中的 item.User.Name。然后我开始了一个我无法工作的潘多拉魔盒实验,主要是在 select 语句中,例如:

select New  //this complains about anonymous type

或者

select New Order(o.OrderNumber,u.Id)  //I can't remember the error here, but red squiggly lines

或者

select New Order { OrderNumber = o.OrderNumber, UserName = u.Name}  //VS complains about not referencing the Users table, it wants to put a UserName field or property stub in my model, which if I do that, then it errors in the cshtml again as I'm guessing because I don't have a UserName in my Orders table?

有几次,我得到了上面的查询,但是当尝试再次访问 cshtml 中的 Users 表时,它抛出了一个异常。我的视图模型控制器如下所示:

public ActionResult Index()
{

var ordersummary = new OrdersSummary();
var viewModel = new OrderSummary
  {
    Orders = ordersummary.GetOrders(),
    OrdersTotal = ordersummary.GetOrdersTotal(),
  };

return View(viewModel);
}

我的 viewModel 模型如下所示:

public class OrderSummary
    {
        public List<Order> Orders { get; set; }
        public decimal OrdersTotal { get; set; }
        public virtual User Users { get; set; }
    {

我的订单模型基本上使用相同的公共虚拟用户用户遍历数据库中的不同列,这与从 ActionResult 中提取的列表一起正常工作。

public class Order
    {

        public int Id { get; internal set; }
        public int UserId { get; set; }
        public int OrderNumber { get; set; }
        ...
        ...
        public virtual User Users { get; set; }
    }

我不禁认为我在我的模型或控制器中做了一些根本错误的事情,而不是在 linq 语句的语法中。任何帮助深表感谢。

更新:我现在已经浏览了一些教程,我基本上是想在这里模仿这个页面(它从 ViewModels 开始,尽管我的 OrderSummary 模型源于上面的 ShoppingCart GetCartItems 等):

http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-8

但是,上面的教程不需要 sql join。想象一下一个工单系统,其中您有工单(订单)和技术人员(用户),并且您正试图将工单分配给技术人员(每张工单一个技术人员,但有些工单可能还没有为他们分配技术人员,也就是空),而我'我试图创建的是概览部分,您在其中查看所有票证和分配给表格中这些票证的技术人员,然后是进一步的统计信息,例如票证总数或最终 TechA 有 x 票证。所以,我需要订单数据库中的所有信息和用户数据库中的名称,然后能够在索引页面上引入多条信息。

我注意到一些教程使用额外的表来加入 Id。所以,在我的例子中,一个额外的表只包含 OrderId 和 UserId。这可能是一种更好的加入方式(“加入”因为缺乏正确的术语)吗?

4

2 回答 2

0

如果你想使用匿名类型,你可以IEnumerable<dynamic>像以前一样返回和工作;

public IEnumerable<dynamic> GetOrders()
{
    var orders = from order in db.Orders
                 join u in db.Users on order.UserId equals u.Id into ou
                 where order.UserId == uId
                 from user in ou.DefaultIfEmpty()
                 select new { order, user };

    return orders.ToList();
}

var item = GetOrders().First();
item.order.Number        // (Orders table)
item.user.Name           // (joined Users table)
于 2013-06-11T17:38:59.100 回答
0

所以,完整的答案如下:

我在评论中提到的 cshtml 怪异是由于:

“object”不包含“X”的定义

匿名对象由编译器作为内部发出。Razor 视图由 ASP.NET 运行时自动编译为单独的程序集。这意味着您无法访问控制器中生成的任何匿名对象。

所以,这很糟糕,它不喜欢上面的匿名查询,即使我在调试时可以从两个表中看到信息(当我将鼠标悬停在我的 cshtml 中的项目上时)。无论如何,我仍然按照 Joachim 的建议使用“动态”,尽管这里的人说这可能不是最好的做事方式。但是,我不得不将我的 linq 查询更改为以下内容以消除匿名性:

var orders = from order in db.Orders
             join u in db.Users on order.UserId equals u.Id into ou
             where order.UserId == uId
             from user in ou.DefaultIfEmpty()
             select new OrderSummary 
               { 
               OrderNumber = order.OrderNumer, 
               UserName = user.Name
               };

诀窍是(无论如何对我来说):

  1. 在我“选择”一个“新的”“订单”(以及其他几件事)之前,而不是“订单摘要”。我从来没有真正清楚这个值应该是“选择新的 ViewModel 名称,或者我想在其他情况下只是模型名称”。
  2. 在括号内,“OrderNumber =”可以任意命名。但是你必须在你的 ViewModel 中创建一个属性存根,在我的例子中是 OrderSummary。(VS 将为您提供创建属性存根的下拉选项。)我认为它是从 ViewModel 中定义的订单列表中提取此信息,但我猜仍然需要属性存根。我还希望不必定义我所有的订单列(即在 SQL 中查找订单。*),但我想这是唯一的选择。

所以然后在我的 Index.cshtml 中,我做的和原来的类似,除了在我定义它们时调用上面的值:

@foreach (var item in Model.Orders) {
@item.UserName //(joined Users table) *This is the only line that changed.
@item.OrderNumber //(Orders table)}

我的控制器在这一切中从未改变......我认为就是这样。我希望这可以避免其他人在将来尝试设置 ViewModel 时感到头疼。活到老,学到老。我的编程术语非常薄弱,所以如果我使用了任何错误的措辞,我深表歉意。祝你好运。

于 2013-06-13T08:33:21.630 回答