如何使用3包括优化实体框架查询

时间:2012-12-13 16:56:22

标签: c# entity-framework

我在.Net 4上使用EF 5

我有以下型号:

public class Order
{

    [Key]
    public int Id { get; set; }
    public string OrderId { get; set; }

    public Address BillingAddress { get; set; }
    public Address DeliveryAddress { get; set; }
    public ICollection<OrderLine> OrderLines { get; set; }
}

public class OrderLine
{
    [Key]
    public int Id { get; set; }

    public string Description { get; set; }
    public decimal UnitPrice { get; set; }
    public int Quantity { get; set; }
    public string SKU { get; set; }
    public decimal ShippingCost { get; set; }
    public decimal Tax { get; set; }
}

public class Address
{
    [Key]
    public int Id { get; set; }
    public string Addressee { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string AddressLine3 { get; set; }
    public string Town { get; set; }
    public string County { get; set; }
    public string Country { get; set; }
    public string Postcode { get; set; }
}

和型号配置:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>().HasMany(x => x.OrderLines).WithRequired().WillCascadeOnDelete();
    modelBuilder.Entity<Order>().HasOptional(x => x.BillingAddress).WithOptionalDependent().WillCascadeOnDelete();
    modelBuilder.Entity<Order>().HasOptional(x => x.DeliveryAddress).WithOptionalDependent().WillCascadeOnDelete();

    base.OnModelCreating(modelBuilder);
}

当我运行以下查询时,我得到 19联接的sql,这对于简单的关系来说似乎过分了

context.Orders
       .Where(x => x.OrderId == orderId)
       .Include(x => x.OrderLines)
       .Include(x => x.BillingAddress)
       .Include(x => x.DeliveryAddress)
       .FirstOrDefault();

我做错了吗?是否有不同的格式化linq查询来优化生成的SQL?

编辑:

这是实际查询:https://gist.github.com/4278014

1 个答案:

答案 0 :(得分:1)

我认为问题在于结算和投放地址上的WithOptionalDependent。这会在地址和订单之间创建1:1的关系,即使这些表设置为1:多关系。

如果您更改配置以使用WithMany

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>().HasMany(x => x.OrderLines).WithRequired().WillCascadeOnDelete();
    modelBuilder.Entity<Order>().HasOptional(x => x.BillingAddress).WithMany().WillCascadeOnDelete();
    modelBuilder.Entity<Order>().HasOptional(x => x.DeliveryAddress).WithMany().WillCascadeOnDelete();

    base.OnModelCreating(modelBuilder);
}

查询更简单,基本上等同于:

...
FROM [Orders]
LEFT OUTER JOIN [Addresses] As B ON [Orders].[BillingAddress_Id] = B.[Id]
LEFT OUTER JOIN [Addresses] As D ON [Orders].[DeliveryAddress_Id] = D.[Id]
LEFT OUTER JOIN [OrderLines] ON [Orders].[Id] = [OrderLines].[Order_Id]