实体框架可查询延迟为大对象与许多条件LinqtoEntity

本文关键字:对象 许多 条件 LinqtoEntity 框架 查询 延迟 实体 | 更新日期: 2023-09-27 18:05:04

我正在尝试重构一个大型物业管理系统的存储库层中一些非常慢的代码。

最初的开发团队遵循的模式是,他们不理解IQueryable延迟执行的本质。

下面是一个代码示例:
public PropertyDTO GetPropertyByPropertyAuctionID(Guid propertyAuctionId)
{
    PropertyDTO property = null;
    var result =
        (
            from pa in databaseContext.PropertyAuction
            join a in databaseContext.Auction on pa.AuctionID equals a.AuctionID into suba
            from sa in suba.DefaultIfEmpty()
            join an in databaseContext.AuctionNotifications
            on sa.AuctionNotificationsID equals an.AuctionNotificationsID into suban
            from san in suban.DefaultIfEmpty()
            where pa.PropertyAuctionID == propertyAuctionId
            where pa.IsDeleted == null || !(bool)pa.IsDeleted
            select new
            {
                PropertyAuction = pa,
                AuctionNotifications = san
            }
        ).FirstOrDefault();
    if (result != null)
    {
        var start = DateTime.Now;
        property = ConvertPropertyFromDatabase(result.PropertyAuction, result.AuctionNotifications);
        //end can be upwards of 10-12 seconds per record
        var end = DateTime.Now - start;
    }
    else
    {
        throw CustomException.NotFound;
    }
    return property;
}
internal PropertyDTO ConvertPropertyFromDatabase(PropertyAuction propertyAuction, AuctionNotifications auctionNotifications = null)
{
    Property property = null;
    PropertyDTO dtoProperty = new PropertyDTO()
    {
        PropertyAuctionID = propertyAuction.PropertyAuctionID
    };
    if (propertyAuction.PropertyID.HasValue)
    {
        dtoProperty.PropertyID = propertyAuction.PropertyID.Value;
        property = propertyAuction.Property;
        dtoProperty.IsSimulcastAuction = propertyAuction.IsSimulcastAuction;
        dtoProperty.IsSold = propertyAuction.IsSold;
        dtoProperty.PropertyExecutionInitialValue = propertyAuction.ExecutionInitialValue;
    }
    if (propertyAuction.User4 != null && !string.IsNullOrEmpty(propertyAuction.User4.Profile1.FirstName) && !string.IsNullOrEmpty(propertyAuction.User4.Profile1.LastName))
    {
        dtoProperty.OfferAdministratorFirstName = propertyAuction.User4.Profile1.FirstName;
        dtoProperty.OfferAdministratorLastName = propertyAuction.User4.Profile1.LastName;
        dtoProperty.OfferAdministratorUserID = propertyAuction.OfferAdministratorUserID;
    }
    if (propertyAuction.AuctionID.HasValue)
    {
        dtoProperty.AuctionID = propertyAuction.AuctionID;
        string auctionStartDateString = String.Empty;
        if (propertyAuction.Auction != null)
        {
            if (propertyAuction.Auction.AuctionStartDate.HasValue)
            {
                auctionStartDateString = propertyAuction.Auction.AuctionStartDate.Value.Year + "-" + propertyAuction.Auction.AuctionStartDate.Value.Month.ToString().PadLeft(2, '0') + "-" + propertyAuction.Auction.AuctionStartDate.Value.Day.ToString().PadLeft(2, '0') + ": ";
            }
            dtoProperty.HMOnlineAuctionClosingStartDate = propertyAuction.Auction.AuctionClosingDate;
            dtoProperty.AuctionName = auctionStartDateString + propertyAuction.Auction.Title;
            dtoProperty.AuctionPublicSiteName = propertyAuction.Auction.PublicSiteName;
            dtoProperty.AuctionNumber = propertyAuction.Auction.AuctionNumber;
            dtoProperty.AuctionType = propertyAuction.Auction.AuctionType.Value;
            dtoProperty.OriginalAuctionID = propertyAuction.Auction.OriginalAuctionID;
            dtoProperty.AuctionTermsAndConditions = propertyAuction.Auction.TermsAndConditions;
            dtoProperty.BrochureFileName = propertyAuction.Auction.BrochureFileName;
            dtoProperty.BrochureName = propertyAuction.Auction.BrochureName;
            if (propertyAuction.Auction.LuJohnsAuctionDetails != null)
            {
                dtoProperty.LuJohnsAuctionLiveWebcastLink = propertyAuction.Auction.LuJohnsAuctionDetails.LiveWebcastLink;
            }
        }
    }
    if (propertyAuction.PropertyStatus != null)
    {
        dtoProperty.PropertyStatusID = propertyAuction.PropertyStatusID.Value;
        dtoProperty.PropertyStatusValue = propertyAuction.PropertyStatus.Value;
    }
    if (propertyAuction.PropertyAuctionAuctionDetails != null)
    {
        PropertyAuctionAuctionDetails propertyAuctionAuctionDetails = propertyAuction.PropertyAuctionAuctionDetails;
        dtoProperty.PropertyAuctionAuctionDetailsId = propertyAuction.PropertyAuctionAuctionDetailsID;
        SetShowOnWebsiteProperty(dtoProperty, propertyAuction);
        SetWebsiteButtonProperty(dtoProperty, propertyAuctionAuctionDetails, propertyAuctionAuctionDetails.PreSaleMethod,
            propertyAuctionAuctionDetails.AuctionMethod, propertyAuctionAuctionDetails.PostSaleMethod);
    }
//This goes on for an astounding 900 more lines of code
}

正如您可能猜到的那样,这会对数据库进行大量的重复访问。

重构这段代码以使访问数据库的次数最少的最快方法是什么?

实体框架可查询延迟为大对象与许多条件LinqtoEntity

这里的问题是这个ConvertPropertyFromDatabase()方法触发了许多对惰性加载属性的查询。我建议你在DbContext类中像这样进行惰性加载:

Configuration.LazyLoadingEnabled = false;

然后你必须检查哪些属性在这个转换方法中被访问,并重写你的查询,使这些显式加载。