简体   繁体   中英

Reduce Load time with Entity Framework and Lazy loading

C# WinForms: I'm using code first approach with Entity framework v6.2.0 and lazy loading , the problem is that it takes 4 to 5 seconds (only the first time) to load the data in our grid . I would like to reduce this load time. Any help?

public List<ShipmentOrder> GetShipmentOrder()
{    
    var ObjShipmentOrderResult = context.shipmentOrders.ToList();
    List<ShipmentOrderEntity> ObjShipmentOrder = null;

        if (ObjShipmentOrderResult != null)
        {
            ObjShipmentOrder = new List<ShipmentOrderEntity>();
            foreach (var item in ObjShipmentOrderResult)
            {
                context.Entry(item).Reference(e => e.storageGate).Load();
                context.Entry(item).Reference(e => e.shippingOrderStatus).Load();
                context.Entry(item).Reference(e => e.packingOrder).Load();
                ObjShipmentOrder.Add(item);
            }
            context.Database.Connection.Close();
            return AutoMapper.Mapper.Map<List<ShipmentOrder>>ObjShipmentOrder);
        }
        else
        {
            return null;
        }
}

Using Automapper you don't need to worry about lazy loads:

public List<ShipmentOrderViewModel> GetShipmentOrder()
{    
    var query= context.shipmentOrders.AsQueryable();
    return query.ProjectTo<ShipmentOrderViewModel>().ToList();
}

ProjectTo takes an IQueryable (what EF queries normally deal with, though in this case because you are using the full DbSet , we need the AsQueryable() ) and will project into that queryable to load just the data needed for your view model. This will result in an optimized query to the database to load all the fields necessary to populate the list of view models.

A few smells from the original code:

Obviously as the system grows you need to limit the # of records that this will pull back. Simply returning everything in a DbSet will quickly become a big problem as the # of records increases.

I've clarified the naming for the returned object as a View Model to ensure that it differentiates from the Entity class. In some cases the view model may pretty much map fields 1-to-1 with an entity, but passing entities outside of the scope of a DbContext is rife with issues, and even dual-purposing an entity by selecting a new, detached copy and treating it like a view model isn't advisable. (An entity class should always be treated like an entity, it gets confusing down the road if entities may be detached vs. attached, or incomplete representations of data.)

Lastly, why are you closing the underlying database connection in the context explicitly? How is the context scoped? If you are using an IoC container like Autofac, Unity, Ninject, etc. this should be managed automatically as the context is disposed. Provided the context is scoped to the request. If not, where is the context constructed? If there is a need to close the connection then the context should be scoped with a using() block until you are able to implement an IoC container to manage its lifetime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM