4

We have a performance problem with EF (Entity Framework). The first screen that calls EF takes much more time to open than the second one. There is no difference in the loading time if the second screen is the same as the first or a completely different one; all other screens will be fast.

We use the Code First API to create a ‘database First’ version of EF. To do this, we use T4 Templates to generate our entities class from the database table. One class is created by table. They are mapped in ‘OnModelCreating()’ We decided to go this way because we needed to separate our entity in three different layers (namespaces and assemblies):

  1. Common Framework
  2. Project Framework
  3. Project Sector

The entities of each of these layers need to be linked to other entities in the previous layers. We tried to use edmx files but we did not find how to put the entities in different namespaces in the same edmx.

We also generate additional classes that are linked to the entities class. Presently, with our T4 Template we generate additional classes that the programmer can use to extend the entities property or to add validation.

The generated entities are the classes that the T4 Template creates with properties for every table column. The Entities is a class that extends the generated class where the programmer can add code. This is the class that is mapped to the table. The validator class is called when the other classes are modified or when the data is saved to database. We need to find a way to pre-generate our view with code first or to have the same flexibility of code first with the edmx.

Example:

ParameterBase.Generated.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Xml.Linq;
using Keops.Common.Data;
using Keops.Common.Validation;
using Keops.Common.Validators.Framework;

namespace Keops.Common.Entities.Framework
{
    public abstract class ParameterBase
        : EntityBase
        , IHaveAValidator
        , IDatabaseOriginAware
    {
        protected ParameterBase()
        {
            ParameterValueList = new HashSet<ParameterValue>();
            Validator = new ParameterValidator((Parameter)this);
        }

        #region Database columns

        public string Code
        {
            get { return _code; }
            set
            {
                if (_code != value)
                {
                    _code = value;
                    RaisePropertyChanged("Code");
                }
            }
        }
        private string _code;

        public bool IsEditable
        {
            get { return _isEditable; }
            set
            {
                if (_isEditable != value)
                {
                    _isEditable = value;
                    RaisePropertyChanged("IsEditable");
                }
            }
        }
        private bool _isEditable;

        public bool IsVisible
        {
            get { return _isVisible; }
            set
            {
                if (_isVisible != value)
                {
                    _isVisible = value;
                    RaisePropertyChanged("IsVisible");
                }
            }
        }
        private bool _isVisible;

        public int ParameterID
        {
            get { return _parameterID; }
            set
            {
                if (_parameterID != value)
                {
                    _parameterID = value;
                    RaisePropertyChanged("ParameterID");
                }
            }
        }
        private int _parameterID;

        public int ValueTypeID
        {
            get { return _valueTypeID; }
            set
            {
                if (_valueTypeID != value)
                {
                    _valueTypeID = value;
                    RaisePropertyChanged("ValueTypeID");
                }
            }
        }
        private int _valueTypeID;

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name!= value)
                {
                    _ name = value;
                    RaisePropertyChanged("Name ");
                }
            }
        }
        private string _ name;

        #endregion Database columns

        #region Navigation parents

        [ForeignKey("ValueTypeID")]
        public ValueType ValueType
        {
            get { return _valueType; }
            set
            {
                if (_valueType != value)
                {
                    _valueType = value;
                    ValueTypeID = value == null
                        ? 0
                        : value.ValueTypeID;
                    RaisePropertyChanged("ValueType");
                }
            }
        }
        private ValueType _valueType;

        #endregion Navigation parents

        #region Navigation children

        public virtual ICollection<ParameterValue> ParameterValueList { get; set; }

        #endregion Navigation children

        #region IHaveAValidator

        public ValidatorBase<Parameter> Validator { get; private set; }

        IValidator IHaveAValidator.Validator
        {
            get { return Validator; }
        }

        #endregion

        #region IDatabaseOriginAware

        public bool IsFromDatabase { get; set; }

        string IDatabaseOriginAware.FullTableName { get { return "Framework.Parameter"; } }       

        #endregion
    }
}

Parameter.cs

namespace Keops.Common.Entities.Framework
{
    public class Parameter : Parameter Base
    {
        //Add custom methods here
    }
}

ParameterValidatorBase.Generated.cs

using System;
using System.Data.Entity;
using System.Linq.Expressions;
using Keops.Common.Entities.System;
using Keops.Common.Validation;

namespace Keops.Common.Validators.System
{
    public abstract class ParameterValidatorBase : ValidatorBase<Parameter>
    {
        private readonly Parameter _entity;

        protected ParameterValidatorBase(Parameter entity)
            : base(entity)
        {
            _entity = entity;
        }

        protected ParameterEntity { get { return _entity; } }
    }
}

ParameterValidator.cs

using Keops.Common.Entities.System;

namespace Keops.Common.Validators.System
{
    public class ParameterValidator : ParameterValidatorBase
    {
        internal ParameterValidator(Parameter entity)
            : base(entity)
        {
        }

        //Define custom rules here
    }
}
1
  • 1
    Have you tried performing some measurements to see where the slowdown is? I suspect that it occurs when you first instantiate your EF DataContext object. Commented Jul 19, 2012 at 15:49

2 Answers 2

2

After more research, we found a blog post from Pawel Kadluczka:

Entity Framework Code First View Generation Templates On Visual Studio Code Gallery

He created a T4 Template that can be used to generate view from Code First.

Sign up to request clarification or add additional context in comments.

Comments

0

Easiest way around this is to set a call to your database on ApplicationStart.

So the first "screen" viewed will be generating the 2nd call.

and it's pretty normal for the first usage of an ORM to take some time to initialise.

2 Comments

We already do this, but we want to minimize the loading time. We know that it is possible to remove the first time overload by pre-generate the view with edmx. We want to know if it is possible to do something similar with Code-First
you don't need to pre-generate the view - In NHibernate you'd set up the SessionFactory in ApplicationStart, I haven't found the equivalent in EF, but making any call to the context works just as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.