jeudi 1 septembre 2016

Extract DbContext into instance field within WCF service

I'm new in the field of WCF services and Entity Framework 6, that's why a very fundamental question came up to me. I have a WCF service providing data from a SQL Server database via Entity Framework 6. For this, there are several operations defined within the service. The service is hosted within IIS. Due to several tutorials and blogs, I followed the pattern of creating an instance of my DbContext per operation within an using-statement. So it looks more or less like this:

public class MyService
{
    public List<HouseDto> GetHouses()
    {
        var houseDtos = new List<HouseDto>();

        using (var context = new TestDbContext())
        {
            var houses = context.Houses.ToList();
            foreach (var house in houses)
            {
                var houseDto = house.ToDto();
                houseDtos.Add(houseDto);
            }
        }    

        return houseDtos;
    }

    public List<StreetDto> GetStreets()
    {
        var streetDtos = new List<StreetDto>();

        using (var context = new TestDbContext())
        {
            var streets = context.Streets.ToList();
            foreach (var street in streets)
            {
                var streetDto = street.ToDto();
                streetDtos.Add(streetDto);
            }
        }    

        return streetDtos;
    }
}

Now I want to test the service operation GetHouses(). For this, I refactored the class in the way of having a TestDbContext as an instance field:

public class MyService
{
    private TestDbContext context;

    public MyService()
    {
        context = new TestDbContext();
    }

    internal MyService(TestDbContext context)
    {
        this.context = context;
    }

    public List<HouseDto> GetHouses()
    {
        var houseDtos = new List<HouseDto>();

        var houses = context.Houses.ToList();
        foreach (var house in houses)
        {
            var houseDto = house.ToDto();
            houseDtos.Add(houseDto);
        }    

        return houseDtos;
    }

    public List<StreetDto> GetStreets()
    {
        var streetDtos = new List<StreetDto>();

        var streets = context.Streets.ToList();
        foreach (var street in streets)
        {
            var streetDto = street.ToDto();
            streetDtos.Add(streetDto);
        }

        return streetDtos;
    }
}

This enabled me to inject a mocked TestDbContext and test the whole service operation, not only the DTO creation method ToDto().

Now several questions came up to me: 1. Are there several independent instances of MyService within IIS or does IIS create and hold exactly one instance of MyService (some kind of singleton)? 2. If there is one instance kept alive: does the underlying database connection of TestDbContext in my refactored class (TestDbContext as instance field) ever get closed or will it remain open until GC/the service within IIS stops? 3. If there are several instances: does each web request to MyService imply the creation of a new instance of TestDbContext or is there a more sophisticated logic?

All of these points can be summarized into one essential question: is my refactoring save for production (read AND write) or could I encounter weird phenomena and avoid this pattern?

Especially the two following posts made me feel that my approach could be safe:

I'm very interested in your answers!

PS: Please don't pay too much attention on the code, it is just a sample. Within my production code, the operations are more complex. The question is definitely more related to the underlying "magic", what's is going on behind the scenes, etc.

Aucun commentaire:

Enregistrer un commentaire