优化实体框架6并减少往返次数

时间:2014-07-12 13:25:37

标签: c# performance entity-framework tsql optimization

我已经使用EF6大约一年了,我真的很喜欢它,但作为一名经验丰富的SQL Server程序员,获得最佳性能是非常有趣的。我在网上搜索了很多关于优化和最小化往返的信息,但我没有找到像这样的问题的简单答案。我们使用仅针对我们的SQL Server 2014数据库构建的围绕EF 6的数据层。我们正在接受EF6,但我对目前的表现并不满意。我有更多涉及的方法,但让我问一个更简单的方法,如下面的示例。

在下面的方法中,我想这是圆形跳闸和查询5次?我知道我可以创建一个带有输出参数和往返的存储过程,也许这是正确的方法吗?如何优化此方法以便以最有效和最快的方式返回结果?

    public static DataInspection GetDataInspection(int userId)
    {
        using (var context = new DemoEntities())
        {
            var di = new DataInspection();

            di.TripCount = context.Trips.Count(x => x.userId == userId);
            di.DayCount = context.Days.Count(x => x.userId == userId);
            di.LegCount = context.Legs.Count(x => x.userId == userId);
            di.MinTripSequenceStart = context.Trips.Where(x => x.userId == userId).Min(y => y.seqStartTime);
            di.MaxTripSequenceEnd = context.Trips.Where(x => x.userId == userId).Max(y => y.seqEndTime);

            return di;
        }
    }

这是为用户返回数据的第二种方法。我还想优化此方法以最小化往返行程并以最快的方式执行此方法。这些实体之间没有关系。

    public static UserData GetMetaData(int userId)
    {
        using (var context = new DemoEntities())
        {
            var cloudData = new DemoData();

            var aircraft = context.Aircraft.Where(x => x.userId == userId);
            var aircraftTypes = context.AircraftTypes.Where(x => x.userId == userId);
            var airlines = context.Airlines.Where(x => x.userId == userId);
            var airports = context.Airports.Where(x => x.userId == userId);
            var approaches = context.Approaches.Where(x => x.userId == userId);
            var approachesLegs = context.ApproachesLegs.Where(x => x.userId == userId);
            var binaries = context.BinaryCatalogs.Where(x => x.userId == userId);
            var crews = context.Crews.Where(x => x.userId == userId);
            var employmentEvents = context.EmploymentEvents.Where(x => x.userId == userId);
            var events = context.Events.Where(x => x.userId == userId);
            var hotels = context.Hotels.Where(x => x.userId == userId);
            var notes = context.Notes.Where(x => x.userId == userId);
            var payperiodevents = context.PayperiodEvents.Where(x => x.userId == userId);
            var payrollCategories = context.PayrollCategories.Where(x => x.userId == userId);
            var performance = context.Performances.Where(x => x.userId == userId);
            var positions = context.Positions.Where(x => x.userId == userId);
            var regOpsTypes = context.RegOperationTypes.Where(x => x.userId == userId);
            var usersettings = context.UserSettings.Where(x => x.userId == userId);
            var globalSettings = from p in context.GlobalSettings select p;

            cloudData.Aircraft = AircraftAssembler.ToDTOs(aircraft);
            cloudData.AircraftTypes = AircraftTypeAssembler.ToDTOs(aircraftTypes);
            cloudData.Airlines = AirlineAssembler.ToDTOs(airlines);
            cloudData.Airports = AirportAssembler.ToDTOs(airports);
            cloudData.Approaches = ApproachAssembler.ToDTOs(approaches);
            cloudData.ApproachesLegs = ApproachesLegAssembler.ToDTOs(approachesLegs);
            cloudData.Binaries = BinaryCatalogAssembler.ToDTOs(binaries);
            cloudData.Crews = CrewAssembler.ToDTOs(crews);
            cloudData.EmploymentEvents = EmploymentEventAssembler.ToDTOs(employmentEvents);
            cloudData.Events = EventAssembler.ToDTOs(events);
            cloudData.Hotels = HotelAssembler.ToDTOs(hotels);
            cloudData.Notes = NoteAssembler.ToDTOs(notes);
            cloudData.PayperiodEvents = PayperiodEventAssembler.ToDTOs(payperiodevents);
            cloudData.PayrollCategories = PayrollCategoryAssembler.ToDTOs(payrollCategories);
            cloudData.Performances = PerformanceAssembler.ToDTOs(performance);
            cloudData.Positions = PositionAssembler.ToDTOs(positions);
            cloudData.RegOperationTypes = RegOperationTypeAssembler.ToDTOs(regOpsTypes);
            cloudData.UserSettings = UserSettingAssembler.ToDTOs(usersettings);
            cloudData.GlobalSettings = GlobalSettingAssembler.ToDTOs(globalSettings);

            return cloudData;
        }
    }

我很感激有关使用VS 2013 C#从Entity Framework 6中获得绝对最佳性能的任何提示。我见过公司使用像NHibernate这样的产品,并且遇到了重大的性能问题,现在我以更大规模的方式使用EF 6我也看到了这个我不相信的结果该产品,而是实施,以及我在这里寻求帮助。

2 个答案:

答案 0 :(得分:1)

您可以通过以下方式获得一次往返的数据:

var data = (from trip in context.Trips.Take(1)
            let TripCount = trip.Count(x => x.userId == userId)
            let DayCount = context.Days.Count(x => x.userId == userId)
            let LegCount = context.Legs.Count(x => x.userId == userId)
            let MinTripSequenceStart = trip.Where(x => x.userId == userId).Min(y => y.seqStartTime)
            let MaxTripSequenceEnd = trip.Where(x => x.userId == userId).Max(y => y.seqEndTime)
            select new {
                TripCount,
                DayCount,
                LegCount,
                MinTripSequenceStart,
                MaxTripSequenceEnd
            }).ToList();

最后将automapper复制数据发送到DataInspection类:

var dataInspection = data
            .Select(inspection => AutoMapper.Mapper.DynamicMap(inspection, inspection.GetType(), typeof(DataInspection)))
            .Select(di => di as DataInspection);

答案 1 :(得分:0)

在调查SQL Server 2014 Profiler后观察往返行程以及连接重置和研究各种优化文章之后,我就提出了这个问题。

1)将AsNoTracking()用于只读方法,例如:

var aircraft = context.Aircraft.AsNoTracking().Where(x => x.userId == userId);

2)如果查询将往返,请通过调用代码手动打开连接以使其保持打开状态,如下所示:

    using (var context = new DemoEntities())
    {
        var cloudData = new DemoData();
        context.Database.Connection.Open();

        var aircraft = context.Aircraft.Where(x => x.userId == userId);
        var aircraftTypes = context.AircraftTypes.Where(x => x.userId == userId);
        var airlines = context.Airlines.Where(x => x.userId == userId);
        //....rest of code here
    }

3)对于DataInspection方法,我可以使用连接打开然后5次往返并且没问题但是我选择使用带有输出参数的存储过程来一次数据库并根据我们的需要处理空值