我的应用程序中有一个ADO.Net数据访问层,它使用基本的ADO.Net和CRUD存储过程(每个操作一个,例如Select_myTable、Insert_myTable)。正如您可以想象的那样,在一个大型系统(如我们的系统)中,DA层所需的DB对象的数量非常大。
我一直在研究将layer类重构为EF POCO类的可能性。我已经设法做到了这一点,但当我尝试性能测试时,它变得相当可怕。使用下面的类(create object,set Key to desired value,调用dataselect),100000次数据加载只需要大约47秒(数据库中只有几条记录)。而存储的Proc方法大约需要7秒。
我正在寻找关于如何优化这一点的建议-需要注意的是,我不能改变层公开的功能-只改变它如何实现方法(即我不能将上下文所有权的责任传递给BO层)。
谢谢
public class DAContext : DbContext
{
public DAContext(DbConnection connection, DbTransaction trans)
: base(connection, false)
{
this.Database.UseTransaction(trans);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//Stop Pluralising the Object names for table names.
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//Set any property ending in "Key" as a key type.
modelBuilder.Properties().Where(prop => prop.Name.ToLower().EndsWith("key")).Configure(config => config.IsKey());
}
public DbSet<MyTable> MyTable{ get; set; }
}
public class MyTable : DataAccessBase
{
#region Properties
public int MyTableKey { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool Active { get; set; }
public int CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public int ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
#endregion
#region constructors
public MyTable()
{
//Set Default Values.
Active = true;
Name = string.Empty;
CreatedDate = DateTime.MinValue;
ModifiedDate = DateTime.MinValue;
}
#endregion
#region Methods
public override void DataSelect(System.Data.SqlClient.SqlConnection connection, System.Data.SqlClient.SqlTransaction transaction)
{
using (DAContext ctxt = new DAContext(connection, transaction))
{
var limitquery = from C in ctxt.MyTable
select C;
//TODO: Sort the Query
limitquery = FilterQuery(limitquery);
var limit = limitquery.FirstOrDefault();
if (limit != null)
{
this.Name = limit.Name;
this.Description = limit.Description;
this.Active = limit.Active;
this.CreatedBy = limit.CreatedBy;
this.CreatedDate = limit.CreatedDate;
this.ModifiedBy = limit.ModifiedBy;
this.ModifiedDate = limit.ModifiedDate;
}
else
{
throw new ObjectNotFoundException(string.Format("No MyTable with the specified Key ({0}) exists", this.MyTableKey));
}
}
}
private IQueryable<MyTable1> FilterQuery(IQueryable<MyTable1> limitQuery)
{
if (MyTableKey > 0) limitQuery = limitQuery.Where(C => C.MyTableKey == MyTableKey);
if (!string.IsNullOrEmpty(Name)) limitQuery = limitQuery.Where(C => C.Name == Name);
if (!string.IsNullOrEmpty(Description)) limitQuery = limitQuery.Where(C => C.Description == Description);
if (Active) limitQuery = limitQuery.Where(C => C.Active == true);
if (CreatedBy > 0) limitQuery = limitQuery.Where(C => C.CreatedBy == CreatedBy);
if (ModifiedBy > 0) limitQuery = limitQuery.Where(C => C.ModifiedBy == ModifiedBy);
if (CreatedDate > DateTime.MinValue) limitQuery = limitQuery.Where(C => C.CreatedDate == CreatedDate);
if (ModifiedDate > DateTime.MinValue) limitQuery = limitQuery.Where(C => C.ModifiedDate == ModifiedDate);
return limitQuery;
}
#endregion
}发布于 2013-06-21 00:07:52
启用跟踪时,选择速度会很慢。您绝对应该关闭跟踪并再次测量。
看看我的基准测试
http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html
发布于 2013-10-30 19:57:14
这可能只是个预感但是..。在您的存储过程中,过滤器定义良好,SP处于编译状态,具有良好的执行计划。您的EF查询是从头开始构造的,并在每次使用时重新编译。因此,现在的任务是设计一种方法,在两次使用之间编译和保存您的EF查询。一种方法是重写FilterQuery,使其不依赖于流畅的条件方法链。不是每次参数集更改时都附加或不附加新条件,而是将其转换为一个条件,当满足条件时应用筛选器,或者在不满足条件时由1.Equals(1)之类的内容覆盖。这样就可以编译您的查询,并使其可供重用。支持SQL看起来很时髦,但执行时间应该会有所改善。或者,您可以设计面向方面的编程方法,根据参数值重用编译后的查询。如果我有时间,我会在Code Project上发布一个示例。
https://stackoverflow.com/questions/17216494
复制相似问题