【问题标题】:Get Entity composed of child entities in Entity Framework获取实体框架中由子实体组成的实体
【发布时间】:2013-04-15 19:24:12
【问题描述】:

我有一些由其他实体组成的“复杂”实体。例如“订单”实体:

  • 订购
  • OrderDetail(子)
  • OrderDetailsDiscount(孩子的孩子)
  • 订单支付
  • 订单状态

Order 类的代码:

[MetadataType(typeof(OrderMetadata))]
public partial class Order
{
    public OrderPaymentStatus PaymentStatus {
        get { return Paid ? OrderPaymentStatus.Paid : OrderPaymentStatus.Pending; }
    }

    public bool Paid {
        get {
            return TotalPaid >= Total;
        }
    }

    public decimal TotalPaid {
        get {
            return OrderPayments.Sum(p => p.Amount);
        }
    }

    public decimal TotalRefund {
        get {
            return OrderRefunds.Sum(p => p.Amount);
        }
    }

    public decimal TotalDebt {
        get {
            return Total - TotalPaid + TotalRefund;
        }
    }

    public decimal TotalDiscounts {
        get {
            return ((SubTotal * DiscountPercentage) / 100) + DiscountAbsolute;
        }
    }

    public decimal TotalSurcharges {
        get {
            return ((SubTotal * SurchargePercentage) / 100);
        }
    }

    [DisplayFormat(DataFormatString="{0:C}", ApplyFormatInEditMode = false)]
    public decimal Total {
        get {
            return SubTotal - TotalDiscounts + TotalSurcharges;
        }
    }

    public decimal TotalTax {
        get {
            return (TaxEnabled) ? OrderDetails.Sum(t => t.Taxes): 0;
        }
    }

    public decimal SubTotal {
        get {
            return OrderDetails.Sum(o => o.Total) + TotalTax;
        }
    }

    public decimal DiscountOffers {
        get {
            return OrderDetails.Sum(o => o.DiscountOffers);
        }
    }

    public bool HasOffers {
        get { 
            return DiscountOffers > 0; 
        }
    }

    public decimal SurchargePercentage {
        get {
            return OrderSurcharges.Sum(o => o.ChargePercentage);
        }
    }

    public decimal DiscountPercentage {
        get {
            return OrderDiscounts.Where(o => o.Type == (int)DiscountType.Percentage).Sum(o => o.Value);
        }
    }

    public decimal DiscountAbsolute
    {
        get
        {
            return OrderDiscounts.Where(o => o.Type == (int)DiscountType.Absolute).Sum(o => o.Value);
        }
    }
}

我以动态方式计算订单总数,因此我总是需要从一开始就加载 OrderDetail.*,以避免在呈现 1000 个订单的列表时对数据库进行多次查询,因此我在我的通用存储库中实现了此方法:

    public virtual IQueryable<T> GetAllIncluding(params Expression<Func<T, object>>[] includeProperties)
    {
        IQueryable<T> query = Fetch();

        foreach (var includeProperty in includeProperties)
        {
            query = query.Include(includeProperty);
        }

        return query;
    }

我这样称呼它为我的代码:

    private IEnumerable<Order> GetAllOrders()
    {
        return unitOfWork.OrderRepository.GetAllIncluding(
            o => o.OrderDiscounts,
            o => o.OrderPayments,
            o => o.OrderSurcharges,
            o => o.OrderStates,
            o => o.OrderRefunds,
            o => o.OrderDetails,
            o => o.OrderDetails.Select(d => d.OrderDetailDiscounts),
            o => o.OrderDetails.Select(d => d.OrderDetailOffers),
            o => o.User,
            o => o.Employee,
            o => o.Store,
            o => o.TerminalSession);
    }

好的..它有效..问题是当我必须用这个查询其他复杂对象时,我的用户实体由其他子实体组成,例如:

  • 用户
  • 用户点
  • 用户状态
  • ...

有什么方法可以指示 EF 将一组实体作为一个整体加载,这样我就可以使用完全加载的 Orders 和 Users 进行查询,以避免在请求大量记录时访问数据库(我不想禁用延迟加载)

【问题讨论】:

  • 你不能添加:o =&gt; o.User.GetAllIncluding(o =&gt; u.UserPoint, u =&gt; u.UserState,...)吗?
  • 是的,问题是一个涉及 User.* 和 Order.* 的查询,例如:来自活跃用户的未支付订单,积分少于 100 分
  • 在我看来,您不应该尝试编写适合所有查询的一种尺寸。对于一个用例,您是否需要所有这些内容?我认为(但我可能错了)你应该使用更多定制的查询,包括(远)更少的包含,有时可能还有一些连接。如果你真的想要你可以预加载任何东西。它可能需要一两个查询,但 EF 会很好地修复关系。但同样,我认为您查询了很多数据。
  • 我正在使用 automapper,Order 实体映射到 OrderDTO,因此 automapper 访问 Order 实体的属性以映射 OrderDTO 上的属性,从而生成大量查询到数据库

标签: c# entity-framework database-design


【解决方案1】:
context.Entity.Include("ChildEntity");

context.Entity.Include( x => x.ChildEntity);

如果您需要更多嵌套实体

context.Entity.Include( x => x.ChildEntity.Select( c => c.ChildChildEntity ));

请记住,lambda 表达式位于 System.Data.Entity 命名空间中。

请记住,一般来说,太多的连接比多个数据库调用更糟糕。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多