Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
LINQ只保留了第一条记录的外部联接_Linq - Fatal编程技术网

LINQ只保留了第一条记录的外部联接

LINQ只保留了第一条记录的外部联接,linq,Linq,我正在处理一个连接三个表的LINQ查询。对于订单和订单信息表,对于给定的订单id,我希望每个表中都有一条记录。但是,对于shipprate表,对于给定的订单id,可能有0条、1条或多条记录。对于这个表,我使用了一个左外连接。如果ShipRate表中存在0或1条记录,则下面显示的查询有效,但对于记录数大于1的情况,我只需要选择最近的ShipRate记录。我试图通过更换线路来实现这一点: 来自sr.DefaultIfEmpty()中的发货率 为此: 来自sr.OrderByDescending(r=

我正在处理一个连接三个表的LINQ查询。对于
订单
订单信息
表,对于给定的
订单id
,我希望每个表中都有一条记录。但是,对于
shipprate
表,对于给定的
订单id
,可能有0条、1条或多条记录。对于这个表,我使用了一个左外连接。如果
ShipRate
表中存在0或1条记录,则下面显示的查询有效,但对于记录数大于1的情况,我只需要选择最近的
ShipRate
记录。我试图通过更换线路来实现这一点:

来自sr.DefaultIfEmpty()中的发货率

为此:

来自sr.OrderByDescending(r=>r.CreateDate)中的发货率。取(1)。DefaultIfEmpty()

但是查询需要花费很长时间,就好像它正在加载整个
ShipRate
表一样。我哪里出错了

var query = (from order in db.Orders
                  join info in db.OrderInfo
                      on order.OrderId equals info.OrderId
                  join shipRate in db.ShipRate
                     on info.OrderId equals shipRate.OrderId
                     into sr
                  from shipRate in sr.DefaultIfEmpty()
                  where order.OrderId == orderId
                  select new 
                  {
                      OrderId = order.OrderId,
                      OrderDetail = info.OrderDetail,
                      Carrier = shipRate.Carrier
                  }).SingleOrDefault();

使用正确的模型定义,您的查询如下:

var query = (from order in db.Orders
             where order.OrderId == orderId
             select new
             {
                 OrderId = order.OrderId,
                 OrderDetail = order.OrderInfo.OrderDetail,
                 Carrier = order.OrderInfo.ShipRates.OrderBy(sr =>sr.CreateDate).FirstOrDefault()
             }).SingleOrDefault();

但我不能确定,因为您没有提供示例数据和模型。

塞廷·巴索兹的答案很好:理想情况下,您应该以允许使用导航属性的方式设置模型。如果您使用的是从数据库模式生成的模型,则通常意味着正确设置外键和主键

如果您不能做到这一点,您仍然可以通过编写如下SQL来获得类似的效果:

 var query = (from order in db.Orders
              where order.OrderId == orderId
              let orderInfo = db.OrderInfo.FirstOrDefault(info => order.OrderId == info.OrderId)
              let currentShipRate = db.ShipRate
                  .Where(shipRate => info.OrderId == shipRate.OrderId)
                  .OrderByDescending(shipRate => shipRate.CreateDate)
                  .FirstOrDefault()
              select new 
              {
                  OrderId = order.OrderId,
                  OrderDetail = orderInfo.OrderDetail,
                  Carrier = currentShipRate.Carrier
              }).SingleOrDefault();

然而,LINQtoSQL在构建高级查询方面远不如实体框架好,您描述的症状可能表明它实际上在进行多个数据库往返而不是连接。我建议通过调用查询上的
.ToString()
,或者在LINQPad中执行查询并单击SQL选项卡,来记录您正在生成的查询(在.SingleOrDefault()之前)。这可能会为您提供查询行为不正常的原因的线索。

订单
订单信息
之间似乎存在一对一的关系:每个订单正好有一个订单信息,每个订单信息正好是一个订单的信息,即外键OrderId引用的订单

另一方面,订单和运价之间似乎存在一对多的关系。每个订单都有零个或多个ShipRate,每个ShipRate都是恰好一个订单的ShipRate,即外键OrderId所指的订单

您需要“Orders”的多个属性,每个订单都有一个且唯一的OrderInfo及其零或多个发货率

当你有一对多关系时,你想要“有零或更多子项目的项目”,比如学校和学生,客户有他们的订单,或者在你的情况下:用他们的SHIPRATE订单,考虑使用一个超载的< /P> 在另一个方向:如果您想要一个项目及其外键引用的唯一其他项目,如他就读的学校的学生、创建订单的客户或其唯一订单信息,请使用Queryable.Join

我主要使用GroupJoin的重载,它有一个参数resultSelector,所以我可以选择我想要的属性

int orderId = ...
var ordersWithShipRates = dbContext.Orders.GroupJoin(dbContext.ShipRates,

    order => order.Id,              // from every Order take the primary key
    shipRate => shipRate.OrderId,   // from every ShipRate take the foreign key to Order

    // parameter resultSelector: from every Order, with its zero or more ShipRates
    // make one new
    (order, shipRatesOfThisOrder) => new
    {
        // Select the Order properties that you plan to use:
        Id = order.Id,
        Date = order.Date,
        ...

        ShipRates = shipRatesOfThisOrder.Select(shipRate => new
        {
             // Select the ShipRate properties that you plan to use:
             Id = shipRate.Id,
             Value = shipRate.Value,
             ...
        })
        .ToList(),

        // A simple join to get the one and only OrderInfo
        OrderInfo = dbContext.OrderInfos.Where(orderInfo => orderInfo.Id == order.Id)
            .Select(orderInfo => new
            {
                // Select the orderInfo properties that you plan to use
                Name = orderInfo.Name,
                ...
            })
            .FirstOrDefault(),
   });

        

你能给出一些样本数据和模型吗。你的问题目前还不清楚。当数据库中有适当的关系时,linq查询很少需要联接。这是实体框架吗?LINQ到SQL?它是LINQ到SQL