Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance with Entity Framework Code-First

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
    }
}
like image 743
Martin Pilote Avatar asked Apr 20 '26 15:04

Martin Pilote


1 Answers

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.

like image 119
Martin Pilote Avatar answered Apr 23 '26 06:04

Martin Pilote