Question

I am trying to set up some compiled queries in my project which uses a unit of work design pattern. These queries get reused multiple times during certain requests and making them compiled queries helps a lot in speeding up the application. One thing I noticed is that I have to pass in the datacontext that I am using instead of being able to use the repositories I have set up in my Unit of Work class.

Here is what works:

        private static Func<PivotalDataContext, Binary, Binary, Int32?, IQueryable<Location>> GetLocationFunc
        {
            get
            {
                Func<PivotalDataContext, Binary, Binary, Int32?, IQueryable<Location>> func =
                    CompiledQuery.Compile(
                        (PivotalDataContext db, Binary destCityId, Binary stateId, Int32? cityNeoId) =>
                        (
                            (from cityDest in db.Destination_Cities
                             where 
                             cityDest.Destination_City_Id == destCityId || cityDest.Neo_Id == cityNeoId
                             join destCountry in db.Destination_Countries
                                 on cityDest.Destination_Country_Id equals destCountry.Destination_Country_Id into country
                             from destCountry in country.DefaultIfEmpty()
                             join destCont in db.Destination_Continents
                                 on destCountry.Destination_Continent_Id equals destCont.Destination_Continent_Id into continent
                             from destCont in continent.DefaultIfEmpty()
                             select new Location
                                        {
CityName = destCity.Name,
CountryName = destCountry.Name,
ContinentName = destContinent.Name
                                        })));


                return func;
            }
        }

Here is what I want:

Constructor:

    private static IRepository<Destination_Country> _destCountryRepo;
    private static IRepository<Destination_Continent> _destContinentRepo;
    private static IRepository<Destination_City> _destinationCityRepo;

        public LocationService()
        {
            _destCountryRepo = UnitOfWork.DestCountryRepo;
                    _destCityRepo = UnitOfWork.DestCityRepo;
                    _destContinentRepo = UnitOfWork.DestContinentRepo;
                    _destCountryRepo = UnitOfWork.DestCountryRepo;
        }

Here is the compiled query (I have replaced the calls to the tables from the datacontext to the tables set up in the constructor):

  private static Func<PivotalDataContext, Binary, Binary, Int32?, IQueryable<Location>> GetLocationFunc
            {
                get
                {
                    Func<PivotalDataContext, Binary, Binary, Int32?, IQueryable<Location>> func =
                        CompiledQuery.Compile(
                            (PivotalDataContext db, Binary destCityId, Binary stateId, Int32? cityNeoId) =>
                            (
                                (from cityDest in _destCityRepo.Table
                                 where 
                                 cityDest.Destination_City_Id == _destCityId || cityDest.Neo_Id == cityNeoId
                                 join destCountry in _destCountryRepo.Table
                                     on cityDest.Destination_Country_Id equals destCountry.Destination_Country_Id into country
                                 from destCountry in country.DefaultIfEmpty()
                                 join destCont in _destContinentRepo.Table
                                     on destCountry.Destination_Continent_Id equals destCont.Destination_Continent_Id into continent
                                 from destCont in continent.DefaultIfEmpty()
                                 select new Location
                                            {
    CityName = destCity.Name,
    CountryName = destCountry.Name,
    ContinentName = destContinent.Name
                                            })));


                    return func;
                }
            }

When I try using the tables set up in the UnitOfWork class and I create a breakpoint at the compiled query those tables are for some reason null, even though they are set when the class is created. Is it possible to do this? Or does the compiled query always need a datacontext passed in?

Thanks in advance!

Was it helpful?

Solution

Short answer: Yes, you must pass it in.

The way that your code is structured is that you are providing the DataContext along with the other arguments to execute the query. Because you are hanging this off of a static property, you will always have to pass in the DataContext because it is not static.

But even if you created the query in a non-static context, there isn't a proper circumstance where the DataContext would be created and live as long as the query. You would end up with a long-lived DataContext which is not how it is intended to be used and introduces a lot of problems.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top