Unsure on how to access Include data in C# Linq

c# entity-framework-6 linq

Question

Evening all, I was hoping that someone could help me along with a project that I am working on.

Just before I really start, I just want to make it absolutely clear, I have never done anything like this before past dabbling at home, I am not a C# developer or Database administrator. So please excuse any breaks from best practice, this is the total of 4 weeks worth of learning and banging my head on the desk trying to follow quiet a confusing topic.

So I have (somehow) ended up being tasked with creating a number of websites, and in an effort to make it easier for myself I have tried to create a "templated" system where I use a number of partial pages/parts in a layout page to drive the website via data.

I have created the below database structure, trying to think of all the things I will need, such as turning parts on and off and creating a control that creates the menu structure.

Model Diagram

of the back of that I have created the below class that creates all of the various view models that I want to pass to each of the partials in my layout (there are multiple dependant on the site hence the parts instead of one giant layout).

public class PageDetails
{
    public static async Task<DataPageDetailsVM> Get(int companyID, ControllerContext controllerContext)
    {
        using (var dimensionContext = new DimensionContext())
        {
            var cDNAddress    = await CDNAddress.Get();
            var aPIAddress    = await APIAddress.Get();

            var routeDetails  = new RouteDetails(controllerContext);
            var canonicalPath = CanonicalPath.Get(routeDetails);

            var pageDetailsVM = await dimensionContext.PageDetail
                .Where(pde => pde.PageAction.PageController.PageArea.Company.CompanyID == companyID
                              && (pde.PageAction.PageController.PageArea.Area == (routeDetails.Area ?? "Home") 
                                  && !pde.PageAction.PageController.PageArea.Excluded)
                              && (pde.PageAction.PageController.Controller == routeDetails.Controller 
                                  && !pde.PageAction.PageController.Excluded)
                              && (pde.PageAction.Action == routeDetails.Action 
                                  && !pde.PageAction.Excluded))
                .Select(pde => new DataPageDetailsVM
                {
                    PageActionID     = pde.PageActionID,
                    CDNAddress       = cDNAddress,
                    APIAddress       = aPIAddress,
                    Title            = pde.Title,
                    FormattedTitle   = pde.FormattedTitle,
                    TagLine          = pde.TagLine,
                    StrapLine        = pde.StrapLine,

                    Latitude         = pde.PageAction.PageController.PageArea.Company.CompanyAddress
                        .Select(sca => sca.Latitude)
                        .FirstOrDefault(),
                    Longitude        = pde.PageAction.PageController.PageArea.Company.CompanyAddress
                        .Select(sca => sca.Longitude)
                        .FirstOrDefault(),

                    DataRouteVM = new DataRouteVM
                    {
                        PrimaryDomain = pde.PageAction.PageController.PageArea.Company.CompanySettings
                            .Select(scs => scs.PrimaryDomain)
                            .FirstOrDefault(),
                        Area          = (routeDetails.Area ?? "Home"),
                        Controller    = routeDetails.Controller,
                        Action        = routeDetails.Action
                    },

                    DataCompanyVM = new DataCompanyVM
                    {
                        CompanyID = companyID,
                        ShortName = pde.PageAction.PageController.PageArea.Company.ShortName,
                        LongName  = pde.PageAction.PageController.PageArea.Company.LongName
                    },

                    PartHeaderVM = new PartHeaderVM
                    {
                        ShortName  = pde.PageAction.PageController.PageArea.Company.ShortName,
                        CDNAddress =  cDNAddress
                    },

                    PartMetaVM = pde.PageAction.PageController.PageArea.Company.CompanySettings 
                        .Select(cse => new PartMetaVM
                        {
                            ShortName        = pde.PageAction.PageController.PageArea.Company.ShortName,
                            ShortDescription = pde.ShortDescription,
                            LongDescription  = pde.LongDescription,
                            Keywords         = pde.Keywords,
                            MsValidate       = cse.MsValidate,
                            FbAppID          = cse.FbAppID,
                            CanonicalPath    = cse.PrimaryDomain + "/" + canonicalPath,
                            OgImage          = cse.PrimaryDomain + "/" + pde.OgImage,
                            ThemeColor       = cse.ThemeColor
                        })
                        .FirstOrDefault(),

                    PartLinksVM = new PartLinksVM
                    {
                        CanonicalPath = pde.PageAction.PageController.PageArea.Company.CompanySettings
                            .Select(cse => cse.PrimaryDomain)
                            .FirstOrDefault() + "/" + canonicalPath,
                    },

                    PartBreadcrumbVM = new PartBreadcrumbVM
                    {
                        BreadcrumbImage = cDNAddress + pde.BreadcrumbImage,
                        Area            = (routeDetails.Area ?? "Home"),
                        Controller      = routeDetails.Controller,
                        Action          = routeDetails.Action,
                        Title           = pde.Title,
                        TagLine         = pde.TagLine
                    },

                    PartFooterVM = new PartFooterVM
                    {
                        CDNAddress = cDNAddress,

                        DataCompanyAddressVM = pde.PageAction.PageController.PageArea.Company.CompanyAddress
                            .Select(cad => new DataCompanyAddressVM
                            {
                                ShortName    = cad.Company.ShortName,
                                LongName     = cad.Company.LongName,
                                Registration = cad.Company.Registration,
                                AddressLine1 = cad.AddressLine1,
                                AddressLine2 = cad.AddressLine2,
                                AddressLine3 = cad.AddressLine3,
                                AddressLine4 = cad.AddressLine4,
                                Postcode     = cad.Postcode,
                                Phone        = cad.Phone
                            })
                            .FirstOrDefault(),

                        DataCompanySocialVM = pde.PageAction.PageController.PageArea.Company.CompanySocial
                            .Select(cso => new DataCompanySocialVM
                            {
                                FacebookAddress = cso.FacebookAddress,
                                LinkedInAddress = cso.LinkedInAddress,
                                TwitterAddress  = cso.LinkedInAddress
                            })
                            .FirstOrDefault()
                    }
                })
                .FirstAsync();

            return pageDetailsVM;
        }
    }
}

My question is I am having to do multiple selects such as:

pde.PageAction.PageController.PageArea.Company.CompanySettings
                        .Select(scs => scs.PrimaryDomain)
                        .FirstOrDefault(),

When I am pretty sure I can use .Include at the top some how and the use a . noted value instead.

But I cant seem to work out how.

I hope that makes sense, and any feedback would be appreciated.

Edit - So just to build on this, basically I have a layout that builds all the bits off a layoutvm class then pass all the "bits" to all the partials

<body class="loading-overlay-showing" data-plugin-page-transition data-loading-overlay data-plugin-options="{'hideDelay': 500}">
@Html.Partial("~/Views/Shared/DisplayTemplates/_Loader.cshtml")
<div class="body">
    @if (isCustomerArea)
    {
        @Html.Partial("~/Areas/Customer/Views/Shared/DisplayTemplates/_Header.cshtml", Model.DataPageDetailsVM.PartHeaderVM)

    }
    else
    {
        @Html.Partial("~/Views/Shared/DisplayTemplates/_Header.cshtml", Model.DataPageDetailsVM.PartHeaderVM)
    }
    <main>
        @if ((ViewContext.RouteData.Values["controller"].ToString() == "Home" && ViewContext.RouteData.Values["action"].ToString() != "Index") || ViewContext.RouteData.Values["controller"].ToString() != "Home")
        {
            @Html.Partial("~/Views/Shared/DisplayTemplates/_Breadcrumb.cshtml", Model.DataPageDetailsVM.PartBreadcrumbVM)
        }
        @RenderBody()
    </main>
    @if (isCustomerArea)
    {
        @Html.Partial("~/Areas/Customer/Views/Shared/DisplayTemplates/_Footer.cshtml", Model.DataPageDetailsVM.PartFooterVM)

    }
    else
    {
        @Html.Partial("~/Views/Shared/DisplayTemplates/_Footer.cshtml", Model.DataPageDetailsVM.PartFooterVM)
    }
</div>
<section>
    @Scripts.Render(Model.DataPageDetailsVM.CDNAddress + "Common/js-footer")
    @Scripts.Render(Model.DataPageDetailsVM.CDNAddress + CompanyDetails.COMPANYID + "/js-footer")
    @RenderSection("scripts", required: false)
</section>

I have a layout class:

    public abstract class LayoutVM
{
    public virtual DataPageDetailsVM DataPageDetailsVM { get; set; }
}

which pulls all the bits in.

Then each page inherits from that layout vm:

    public class PageRetailVM : LayoutVM
{
    public SuggestedServicesVM SuggestedServicesVM { get; set; }
}

then my page controller becomes very simple, not only do I get access to all the layout data, but the code for the page becomes really small:

    [HttpGet]
    [AllowAnonymous]
    public async Task<ActionResult> Retail()
    {
        PageRetailVM pageRetailVM = new PageRetailVM
        {
            DataPageDetailsVM   = await PageDetails.Get(CompanyDetails.COMPANYID, ControllerContext),
            SuggestedServicesVM = await PartSuggestedServices.Get(CompanyDetails.COMPANYID, ControllerContext)
        };

        return View(pageRetailVM);
    }

That is what the PageDetails class is for

1
0
2/23/2020 1:03:18 AM

Popular Answer

Include() allows you to indicate which related entities should be read from the database as part of the same query. It allows you to make eager loading for performance purposes.

DbContext class enables lazy loading by default, when the entity is first read, related data isn't retrieved. However, the first time you attempt to access a navigation property, the data required for that navigation property is automatically retrieved. This results in multiple queries sent to the database.

You could Include() related data that you need and simply save it to a variable for further processing.

1
2/22/2020 11:01:38 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow