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):
- Common Framework
- Project Framework
- 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
}
}