实体框架代码优先的性能
Posted
技术标签:
【中文标题】实体框架代码优先的性能【英文标题】:Performance with Entity Framework Code-First 【发布时间】:2012-07-19 15:45:44 【问题描述】:EF(实体框架)存在性能问题。调用 EF 的第一个屏幕比第二个屏幕需要更多时间来打开。如果第二个屏幕与第一个屏幕相同或完全不同,则加载时间没有差异;所有其他屏幕都会很快。
我们使用 Code First API 来创建 EF 的“数据库优先”版本。为此,我们使用 T4 模板从数据库表中生成实体类。一个类是由表创建的。它们在“OnModelCreating()”中映射我们决定采用这种方式,因为我们需要将实体分成三个不同的层(命名空间和程序集):
-
通用框架
项目框架
项目部门
每个层的实体都需要链接到前一层中的其他实体。我们尝试使用 edmx 文件,但没有找到如何将实体放在同一个 edmx 中的不同命名空间中。
我们还生成链接到实体类的其他类。目前,通过我们的 T4 模板,我们生成了额外的类,程序员可以使用这些类来扩展实体属性或添加验证。
生成的实体是 T4 模板为每个表列创建的具有属性的类。实体是一个扩展生成的类的类,程序员可以在其中添加代码。这是映射到表的类。当修改其他类或将数据保存到数据库时,将调用验证器类。 我们需要找到一种方法,先使用代码预先生成我们的视图,或者使用 edmx 让代码先具有相同的灵活性。
例子:
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
【问题讨论】:
您是否尝试过执行一些测量来查看减速在哪里?我怀疑它发生在您第一次实例化 EF DataContext 对象时。 【参考方案1】:经过更多研究,我们发现了 Pawel Kadluczka 的一篇博文:
Entity Framework Code First View Generation Templates On Visual Studio Code Gallery
他创建了一个T4 Template,可用于从 Code First 生成视图。
【讨论】:
【参考方案2】:解决此问题的最简单方法是在 ApplicationStart 上设置对数据库的调用。
因此,查看的第一个“屏幕”将生成第二个调用。
第一次使用 ORM 需要一些时间来初始化是很正常的。
【讨论】:
我们已经这样做了,但我们希望尽量减少加载时间。我们知道可以通过使用edmx 预先生成视图来消除第一次重载。我们想知道是否可以使用 Code-First 做类似的事情 您不需要预先生成视图 - 在 NHibernate 中,您已经在 ApplicationStart 中设置了 SessionFactory,我在 EF 中没有找到等效项,但是对上下文进行任何调用都有效也一样。以上是关于实体框架代码优先的性能的主要内容,如果未能解决你的问题,请参考以下文章