Linq查询加入表Mvc Asp

时间:2015-11-27 18:07:02

标签: c# asp.net-mvc linq

我有这些表用于电子商务应用程序,我在SQL中创建了这些表,然后添加了ADO.NET并选择了Code First。使用的MVC默认身份代码优先:

Users: UserId(PK), FName, LName

Product: ProductId(PK), ProductName, ProductPrice, CategoryId(FK)

Category: CategoryId(PK), CategoryName

Orders: OrderId(PK), OrderTotal, UserId(FK)

OrderDetails: OdId(PK), OrderId(FK), ProductId(FK), Quantity

每种产品都与某些类别相关。用户可以下订单,进一步的订单明细存储在OrderDetails表中。

我想根据用户之前购买的产品获取产品,我已将其存储在订单和订单详细信息表中。

示例如果用户A从“服装”类别购买产品“衬衫”,则订单存储在订单表中,产品ID存储在OrderDetails表中

我写这篇文章只是为了给你们一个想法(我希望它清楚)

public ActionResult Index()
{
    string user = User.Identity.GetUserName();
    var q = db.OrderDetails.Where(m => m.Order.Email == user).ToList();
    var query = (from pd in db.Products
                 join od in db.OrderDetails on pd.ProductId equals od.ProductID
                 join oo in db.Orders on od.OrderId equals oo.OrderId

                 where oo.UserId == user
                 select new
                 {   
                     ProductName = pd.Name,
                     ProductPrice = pd.Price, // six value
                 }).ToList();
    return View(query);
}

以下是数据库图表的截图:

enter image description here

1 个答案:

答案 0 :(得分:0)

从您的评论中,我认为您当前的错误是

  

传递到字典中的模型项是类型的   ' System.Collections.Generic.List1 [<> f__AnonymousType92 [System.String,System.Nul lable1 [System.Decimal]]]',但此词典需要类型的模型项   ' System.Collections.Generic.IEnumerable1 [FypStore.Models.Product]'

看起来您的Index视图绑定到Product类对象的集合,如此

@model IEnumerable<YourEntityNamespace.Product>

但是在索引操作中,从LINQ连接表达式开始,您正在使用2个属性ProductName和ProductPrice对匿名类型进行投影。

var query = (from pd in db.Products
                 join od in db.OrderDetails on pd.ProductId equals od.ProductID
                 join oo in db.Orders on od.OrderId equals oo.OrderId

                 where oo.UserId == user

                 select new  // Projection to Anonymous type
                 {   
                     ProductName = pd.Name,
                     ProductPrice = pd.Price, // six value
                 }).ToList();

要解决当前问题,您可以删除投影并选择pd。

var query = (from pd in db.Products
                 join od in db.OrderDetails on pd.ProductId equals od.ProductID
                 join oo in db.Orders on od.OrderId equals oo.OrderId

                 where oo.UserId == user                    
                 select pd).ToList();

即使这会解决您当前的错误,但这不是最佳解决方案。通过上述解决方案,我们将整个产品(在当前过滤器之后)实体传递给视图。这些实体可能具有其他导航属性,并且在循环中在剃刀视图中访问它们将再次生成SQL查询。阅读有关此方法问题的更多信息here

您最好的解决方案是在一个公共项目中创建一个新的viewmodel类/ DTO类,该项目可以访问您的UI项目和数据访问项目(如果您有多个项目),并在您的LINQ表达式投影中使用它并绑定您的剃刀查看新视图模型类的集合。

public class ProductVM
{
  public string ProductName {set;get;}
  public decimal ProductPrice {set;get;}
}

在你的LINQ表达式中,在投影中使用它。

var products = (from pd in db.Products
             join od in db.OrderDetails on pd.ProductId equals od.ProductID
             join oo in db.Orders on od.OrderId equals oo.OrderId

             where oo.UserId == user
             select new ProductVM
             {   
                 ProductName = pd.Name,
                 ProductPrice = pd.Price, // six value
             }).ToList();
     return View(products);

由于我们现在将一个ProductVM类对象列表返回给我们的视图,我们应该将剃刀视图更新为

@model List<YourNamespace.ProductVM>
<h1>Products</h1>
@foreach(var p in Model)
{
  <h2>@p.ProductName - @p.ProductPrice </h2>
}

如果您认为绝对需要,可以向视图模型添加更多属性

相关问题