[C#][Entity framework] Een heleboel queries tijdens debuggen

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
Een cross-post met Stack Overflow maar weinig respons daar.

Ik zit met het volgende probleem:
Als ik mijn applicatie debug in Visual Studio dan zie ik regelmatig een soort van uitbraak van tot wel 80 de zelfde queries tijdens een page load. Het is ook niet vooruit te branden. Het is een code first project wat ik geerfd heb van een andere programmeur. Ik doe al mijn database migraties met SQL scripts aangezien er ook altijd data overgepompt moet worden enzovoort. Ook makkelijker met CI en terug rollen van dingen.

Het lijkt er op dat EF probeert om te checken of tables bestaan en ze dan aan te maken. Maar ik heb inmiddels wat maatregelen genomen om dat tegen te gaan:

C#:
1
2
3
4
5
6
7
public class MyConfig : DbConfiguration
{
    public MyConfig()
    {
        SetDatabaseInitializer<DatabaseContext>(null);
    }
}



C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
public DatabaseContext()
        : base("DefaultConnection")
    {
        Configuration.LazyLoadingEnabled = false;
        Database.SetInitializer<DatabaseContext>(null);
    }

    public DatabaseContext(string connectionString)
        : base(connectionString)
    {
        Configuration.LazyLoadingEnabled = false;
        Database.SetInitializer<DatabaseContext>(null);
    }


Deze code wordt ook geraakt als ik breakpoints zet dus ik ga er van uit dat al die auto init zut gewoon niet meer werkt. Toch staat mijn hele log vol met:

SQL:
1
2
3
IF db_id(N'dbname') IS NOT NULL SELECT 1 ELSE SELECT Count(*) FROM sys.databases WHERE [name]=N'dbname'
-- en
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@Table

iOS developer


Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 15:15
Doe je al je views precompileren en de model database cachen?

Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
Dat ziet er interessant uit en dat wijst er ook op dat de applicatie trager wordt naar mate er meer tabellen bij komen wat inderdaad wel correspondeert met mijn steeds uitdijende applicatie. Ik ga hier mee aan de slag en ik laat het je weten. Het kan wel even een paar dagen duren voordat de resultaten binnen zijn.

Bedankt!

Ik krijg heel erg sterk het gevoel dat Entity Framework niet echt lekker schaalt, leuk voor een schets applicatietje maar zo gauw het serieus wordt (zowel in query complexiteit als in schaal) gaat het alleen maar tegen werken.

iOS developer


Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 15:15
Klopt. Daarom werken wij tegenwoordig met Bounded Contexts met elke context dus zijn eigen EF model. Andere oplossing is zelfs per Aggegate Root een eigen EF model bouwen.

Acties:
  • 0 Henk 'm!

  • Azer
  • Registratie: Oktober 2003
  • Niet online
Komt het niet doordat je je queries verkeerd uitvoert? Dat hij voorbeeld voor elk item in een verzameling een aparte query gaat uitvoeren? Als dat het geval is zou ik me eens inlezen op het gebied van lazy loading en hoe je je queries kunt optimaliseren.

Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
Azer schreef op zaterdag 06 augustus 2016 @ 21:11:
Komt het niet doordat je je queries verkeerd uitvoert? Dat hij voorbeeld voor elk item in een verzameling een aparte query gaat uitvoeren? Als dat het geval is zou ik me eens inlezen op het gebied van lazy loading en hoe je je queries kunt optimaliseren.
Nee zeker niet, verkeerde queries zou ik wel herkennen. Dit is een soort tabel structuur scanning die EF doet.

iOS developer


Acties:
  • 0 Henk 'm!

  • GrooV
  • Registratie: September 2004
  • Laatst online: 08:04
Is dit alleen tijdens debuggen?

Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
Ik ben met die Entity Framework Tools aan de gang gegaan. Die genereerde een hoop automatische code voor me. Wat deze code wel had maar mijn eigen code niet waren de mappings. Deze mappings heb ik over genomen en met wat prutsen compiled en runt de boel.

Als ik inlog alleen al heb ik deze trits aan nutteloze database calls:

Entity Hell

Let op de scrollbalk. Dus nog tien pagina's met rommelqueries. Voor één pageload |:(

Wat triggert deze queries? Hoe stop ik dit? :'(

[ Voor 30% gewijzigd door BikkelZ op 26-08-2016 19:51 ]

iOS developer


Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 15:15
Beter prutsenb :+ , dit zijn queries die voorkomen worden door de precompiled views

Welke databaseinitializer gebruik je? Daar zou je ook de NullDatabaseInitializer moeten gebruiken.

[ Voor 38% gewijzigd door Xiphalon op 26-08-2016 19:55 ]


Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
Xiphalon schreef op vrijdag 26 augustus 2016 @ 19:52:
Beter prutsenb :+ , dit zijn queries die voorkomen worden door de precompiled views
Ik heb een class DatabaseContext.Views.cs, als ik daar een breakpoint in zet dan wordt die ook geraakt. Voordat de breakpoint geraakt wordt heb ik al 20 queries gedaan en daarna nog een stuk of 80. Volgens mij mis ik een soort Magic Word ergens, vergelijkbaar met het analoge "PLEASE"

----- edit -----

Dit is nu een greep uit mijn code. Breakpoints gezet, alles wordt geraakt dus de NullDatabaseInitializer wordt gezet.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   public class MyConfig : DbConfiguration
    {
        public MyConfig()
        {
            SetDatabaseInitializer<DatabaseContext>(new NullDatabaseInitializer<DatabaseContext>());
            //SetDatabaseInitializer<DatabaseContext>(null);
        }
    }

    public class DatabaseContext : IdentityDbContext<ApplicationUser>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DatabaseContext"/> class.
        /// </summary>
        public DatabaseContext()
            : base("DefaultConnection")
        {
            Configuration.LazyLoadingEnabled = false;
            //SetDatabaseInitializer<BloggingContext>(new NullDatabaseInitializer<BloggingContext>());
            Database.SetInitializer(new NullDatabaseInitializer<DatabaseContext>());
        }

        public DatabaseContext(string connectionString)
            : base(connectionString)
        {
            Configuration.LazyLoadingEnabled = false;
            Database.SetInitializer(new NullDatabaseInitializer<DatabaseContext>());
            //Database.SetInitializer<DatabaseContext>(null);
        }

[ Voor 56% gewijzigd door BikkelZ op 26-08-2016 20:13 ]

iOS developer


Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 15:15
Ik heb even snel door de EF6 code heengekeken en het lijkt erop dat die query op sys.databases gebruikt wordt om te kijken of de database bestaat. Wordt vooral gebruikt in de migraties zag ik snel, maar dat gebruik je niet. Doe je zelf ergens een DatabaseExists call op je ObjectContext?

Ik zie trouwens in je identitycontext in de default constructor een uitgecommente SetDatabaseInitializer voor een andere context. Probeer die eens met de juiste context?

Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
Die call werkt alleen op DbConfiguration, op DbContext is hij net anders. Maar automatische migraties zal wel het probleem zijn inderdaad.

[ Voor 31% gewijzigd door BikkelZ op 27-08-2016 02:41 ]

iOS developer


Acties:
  • 0 Henk 'm!

  • alwinuzz
  • Registratie: April 2008
  • Laatst online: 10-10 12:54
Misschien een idee om EF Profiler te proberen? https://www.hibernatingrhinos.com/products/efprof

Ik heb de nibernate versie kort gebruikt om excessieve queries te verminderen, beviel heel goed.

Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50
alwinuzz schreef op zaterdag 27 augustus 2016 @ 13:15:
Misschien een idee om EF Profiler te proberen? https://www.hibernatingrhinos.com/products/efprof

Ik heb de nibernate versie kort gebruikt om excessieve queries te verminderen, beviel heel goed.
Die tip hielp niet direct, maar veroorzaakte wel een crash direct in App_Start die me weer wees op een niet-standaard Unity / IUnitOfWork implementatie waar ik breakpoints in ben gaan zetten.

Het bleek dat iedere keer dat als hier een breakpoint werd geraakt:

C#:
1
2
3
4
5
6
7
        public DatabaseContext()
            : base("DefaultConnection")
        {
            Configuration.LazyLoadingEnabled = false;
            //SetDatabaseInitializer<BloggingContext>(new NullDatabaseInitializer<BloggingContext>());
            Database.SetInitializer(new NullDatabaseInitializer<DatabaseContext>());
        }


...er twee queries werden aangemaakt. Er wordt dus gewoon iedere page load 40x een DatabaseContext aangemaakt en die DatabaseContext gaat iedere keer weer opnieuw die twee queries uitvoeren.

Ik heb geprobeerd om de DatabaseContext te bufferen waar hij werd aangemaakt, dus naar een static weg te schrijven. Uiteraard ging hij daarna balken over een disposed DbContext want EF wil gewoon iedere keer een nieuwe DbContext. Dus er zijn naar mijn idee een paar oplossingen:

- Niet zo vaak een DatabaseContext aanmaken (maar hoe?)
- De DatabaseContext niet die twee queries laten uitvoeren (maar hoe? hij heeft all een null context)

....of een combinatie van deze twee oplossingen.

iOS developer


Acties:
  • 0 Henk 'm!

  • alwinuzz
  • Registratie: April 2008
  • Laatst online: 10-10 12:54
BikkelZ schreef op zaterdag 27 augustus 2016 @ 18:09:
[...]


Die tip hielp niet direct, maar veroorzaakte wel een crash direct in App_Start die me weer wees op een niet-standaard Unity / IUnitOfWork implementatie waar ik breakpoints in ben gaan zetten.

Het bleek dat iedere keer dat als hier een breakpoint werd geraakt:

C#:
1
2
3
4
5
6
7
        public DatabaseContext()
            : base("DefaultConnection")
        {
            Configuration.LazyLoadingEnabled = false;
            //SetDatabaseInitializer<BloggingContext>(new NullDatabaseInitializer<BloggingContext>());
            Database.SetInitializer(new NullDatabaseInitializer<DatabaseContext>());
        }


...er twee queries werden aangemaakt. Er wordt dus gewoon iedere page load 40x een DatabaseContext aangemaakt en die DatabaseContext gaat iedere keer weer opnieuw die twee queries uitvoeren.

Ik heb geprobeerd om de DatabaseContext te bufferen waar hij werd aangemaakt, dus naar een static weg te schrijven. Uiteraard ging hij daarna balken over een disposed DbContext want EF wil gewoon iedere keer een nieuwe DbContext. Dus er zijn naar mijn idee een paar oplossingen:

- Niet zo vaak een DatabaseContext aanmaken (maar hoe?)
- De DatabaseContext niet die twee queries laten uitvoeren (maar hoe? hij heeft all een null context)

....of een combinatie van deze twee oplossingen.
In nibernate wil je 1 session per request die gemaakt wordt door een singleton sessionFactory. Waarschijnlijk hanteert EF hetzelfde systeem, ik heb zelf geen ervaring met ef. Je kan googelen op "ef session per request", misschien vind je dan een oplossing.

Acties:
  • 0 Henk 'm!

  • vandeGerrit
  • Registratie: Januari 2009
  • Laatst online: 26-08 12:51

vandeGerrit

Well, this can't be right

Moet je de Database.SetInitializer elke keer aanroepen bij het maken van een Context? Het lijkt mij daarom dat hij elke keer besluit om de initializer op nieuw uit te voeren. Ook roept hij volgens mij eerst nu de base aan (dit dus inclusief aanmaken van de database etc), om vervolgens daarna de database initializer op null te zetten.

C#:
1
2
3
4
Database.SetInitializer(new NullDatabaseInitializer<DatabaseContext>());
using (var context = new DatabaseContext())
{
}

Acties:
  • 0 Henk 'm!

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 15:13

mulder

ik spuug op het trottoir

BikkelZ schreef op zaterdag 27 augustus 2016 @ 18:09:
[...]


Die tip hielp niet direct, maar veroorzaakte wel een crash direct in App_Start die me weer wees op een niet-standaard Unity / IUnitOfWork implementatie waar ik breakpoints in ben gaan zetten.

Het bleek dat iedere keer dat als hier een breakpoint werd geraakt:

C#:
1
2
3
4
5
6
7
        public DatabaseContext()
            : base("DefaultConnection")
        {
            Configuration.LazyLoadingEnabled = false;
            //SetDatabaseInitializer<BloggingContext>(new NullDatabaseInitializer<BloggingContext>());
            Database.SetInitializer(new NullDatabaseInitializer<DatabaseContext>());
        }


...er twee queries werden aangemaakt. Er wordt dus gewoon iedere page load 40x een DatabaseContext aangemaakt en die DatabaseContext gaat iedere keer weer opnieuw die twee queries uitvoeren.

Ik heb geprobeerd om de DatabaseContext te bufferen waar hij werd aangemaakt, dus naar een static weg te schrijven. Uiteraard ging hij daarna balken over een disposed DbContext want EF wil gewoon iedere keer een nieuwe DbContext. Dus er zijn naar mijn idee een paar oplossingen:

- Niet zo vaak een DatabaseContext aanmaken (maar hoe?)
- De DatabaseContext niet die twee queries laten uitvoeren (maar hoe? hij heeft all een null context)

....of een combinatie van deze twee oplossingen.
Je moet naar de lifetimemanager voor je IoC container kijken,volgens mij kun je het beste een HierarchicalLifetimeManager voor je context gebruiken.

oogjes open, snaveltjes dicht

Pagina: 1