0

我的应用程序中有一个 ADO.Net 数据访问层,它使用基本的 ADO.Net 和 CRUD 存储过程(每个操作一个,例如 Select_myTable、Insert_myTable)。可以想象,在大型系统(如我们的系统)中,DA 层所需的 DB 对象数量非常多。

我一直在研究将层类重构为 EF POCO 类的可能性。我已经设法做到了,但是当我尝试进行性能测试时,它变得非常可怕。使用下面的类(创建对象,将 Key 设置为所需的值,调用 dataselect),100000 次数据加载只需要大约 47 秒(数据库中只有少数记录)。而存储过程方法大约需要 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


}
4

2 回答 2

1

跟踪打开时选择很慢。您绝对应该关闭跟踪并再次测量。

看看我的基准

http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html

于 2013-06-20T16:07:52.253 回答
0

这可能只是一种预感,但是......在您的存储过程中,过滤器定义良好,SP 处于编译状态,执行计划不错。您的 EF 查询从头开始构建并在每次使用时重新编译。因此,现在的任务变成了设计一种在使用之间编译和保存 EF 查询的方法。一种方法是重写您的 FilterQuery 以不依赖于流畅的条件方法链。每次您的参数集更改时,不要附加或不附加一个新条件,而是将其转换为一个条件,在满足条件时应用过滤器,或者在不满足条件时由类似 1.Equals(1) 的内容覆盖。这样,您的查询可以被编译并可供重复使用。支持的 SQL 看起来很时髦,但执行时间应该会有所改善。或者,您可以设计面向方面的编程方法,其中编译的查询将根据参数值重新使用。如果我有时间,我会在 Code Project 上发布一个示例。

于 2013-10-30T11:57:14.357 回答