测试 ClownFish、CYQ、Entity Framework、Moon、MySoft、NHibernate、PDF、XCode数据访问组件性能_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 测试 ClownFish、CYQ、Entity Framework、Moon、MySoft、NHibernate、PDF、XCode数据访问组件性能

测试 ClownFish、CYQ、Entity Framework、Moon、MySoft、NHibernate、PDF、XCode数据访问组件性能

 2013/7/26 11:21:36  火地晋  博客园  我要评论(0)
  • 摘要:“啊!你在用ORM?会不会性能很差啊?”用数字来说话,打破模糊的、传言的印象。标题提到的组件的增删改查的测试都实现了测试代码,所以除了测试外,也可以把此项目作为各个组件的入门参考demo。源码下载:https://github.com/alifellod/DbAccessLibTest/archive/master.zipgit地址:https://github.com/alifellod/DbAccessLibTest 欢迎园友贡献改进代码。项目使用的是
  • 标签:Framework 测试 数据 hibernate
“啊!你在用ORM?会不会性能很差啊?” 用数字来说话,打破模糊的、传言的印象。

标题提到的组件的增删改查的测试都实现了测试代码,所以除了测试外,也可以把此项目作为各个组件的入门参考demo。

源码下载:https://github.com/alifellod/DbAccessLibTest/archive/master.zip

git地址:https://github.com/alifellod/DbAccessLibTest  欢迎园友贡献改进代码。

项目使用的是.Net Framework 4.0可以使用2010或2012打开。

 

默认测试数据库使用SqlServer

测试前,请先创建数据表Test(使用名为Test的数据库,如果不用这个数据库,请更改数据库连接字符串)

class="code_img_closed" id="code_img_closed_11342730-6925-4b73-ae75-28e145087561" alt="" />logs_code_hide('11342730-6925-4b73-ae75-28e145087561',event)" style="display:none"> CREATE TABLE [dbo].[Test]
(
    [RowId] [int] IDENTITY(1,1NOT NULL,
    [Guid] [varchar](50primary key NOT NULL,
    [Content] [nvarchar](500NULL,
    [CreateDate] [datetime] NULL default getdate(),
    [EditDate] [datetime] NULL
) View Code

测试前清表:truncatetable Test
默认连接字符串是:Data Source=.;Initial Catalog=Test;Integrated Security=True

此程度测试代码使用了接口规范,并没有为了省事耦合在程序里,因此编写修改测试代码非常简单,所以也希望各位园友自己写上一段测试测试。
由于这些组件基本都是第一次使用,所以可能导致部分组件测试代码编写并不合理,敬请指点。
注意:各组件的测试均采用一样的测试思路,也即ORM对ORM,SQL对SQL,循环也是一样的循环。
不必拘泥于15和23的区别,而且要区别10和100的区别,也就是在一个数量级别之间比较。
线程我分别写了Task、ThreadPool和Thread的执行方式,根据自己的喜欢选择。

Task可以很好的取消创建的线程,ThreadPool测试会较为稳定,Thread很容易导致SQL连接池爆破。 测试之前,先预热一下——各个组件进行一定数量执行查询。
先看两张测试图。

 

 

 

数据格式:平均值-最高值-最低值
测试顺序:增、改、删
100“线程” 查询10次 增删改
 

 

ClownFish

Moon

PDF

23-96-2

21-76-6

8-25-4

16-49-2

15-37-5

4-18-2

46-116-3

23-56-3

7-33-3

 

CYQOrm

EFOrm

MoonOrm

MySoftOrm

NHibernateOrm

PDFOrm

XCodeOrm

 

419-560-311

 

23-71-8

10-64-3

46-102-24

21-47-7

12-31-4

15-60-9

889-1611-493

61-137-17

10-29-3

41-267-15

41-103-9

20-54-3

340-623-173

428-1112-255

37-113-15

5-15-2

110-195-52

37-128-7

17-50-3

364-476-246


1000“线程” 查询10次增删改

 

ClownFish

Moon

PDF

9-276-2

13-49-2

7-44-3

22-125-2

7-43-3

9-41-3

20-299-2

10-123-3

8-66-2

 

CYQOrm

EFOrm

MoonOrm

MySoftOrm

NHibernateOrm

PDFOrm

XCodeOrm

591-1376-227

29-306-9

6-52-3

50-386-11

12-259-4

10-48-3

14-231-8

680-1107-382

43-321-11

14-95-2

78-386-13

45-237-7

22-90-4

362-729-177

553-867-233

59-334-12

27-215-14

106-647-18

42-294-4

17-128-3

410-755-199


查询测试,数据行100W
100“线程” 查询返回Top 100
使用没有索引的列RowId排序

 

ClownFish

Moon

PDF

2-19-1

1-9-0

1-47-0

查询采用的根据组件提供的分页或者Top查询功能。
使用没有索引的列RowId排序

 

CYQOrm

EFOrm

MoonOrm

MySoftOrm

NHibernateOrm

PDFOrm

XCodeOrm

3975-5133-267

1452-3668-735

5230-8032-3241

1287-1670-240

3372-6264-954

2629-3825-836

1696-5363-716

使用有索引的列Guid排序

 

CYQOrm

EFOrm

MoonOrm

MySoftOrm

NHibernateOrm

PDFOrm

XCodeOrm

16-32-13

5-8-3

5967-14644-1639

2-5-1

7-127-2

1-17-0

1-9-0

经过测试,发现线程越多,越容易出现问题“超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。”导致访问很不稳定。
一个好的数据访问层应该是可以优雅的接受并处理大并发的访问,而不应该仅仅只盯住表面上的测试数据。
整个程序框架设计良好是更应该花更多心思考虑的。
从上面也可以看到,ORM性能其实并没有一般人想象的那么糟糕。

最后看看程序的代码是怎么样的。

项目目录

测试代码接口

public interface ITest
{
    bool Insert();
    bool Update(string guid, string content);
    DataTable Select(int count);
    List<string> GetGuidList(int count);
    bool Delete(string guid);
} View Code

ClownFish-SQL测试代码

public class ClownFishTest : DbContextHolderBase, ITest
{
    static ClownFishTest()
    {
        DbContext.RegisterDbConnectionInfo("sqlserver""System.Data.SqlClient""@", Control.ConnectionStrings);
    }
    public void TruncateTable()
    {
        DbHelper.ExecuteNonQuery(SqlString.TruncateTable, null, DbContext, CommandKind.SqlTextNoParams);
    }
    public bool Insert()
    {
        var parameter = new { Guid = Guid.NewGuid(), Content = string.Empty };
        return (DbHelper.ExecuteNonQuery(SqlString.Insert, parameter, DbContext, CommandKind.SqlTextWithParams) > 0);
    }
    public bool Update(string guid, string content)
    {
        var parameter = new { Guid = guid, Content = content };
        return (DbHelper.ExecuteNonQuery(SqlString.Update, parameter, DbContext, CommandKind.SqlTextWithParams) > 0);
    }
    public DataTable Select(int count)
    {
        return DbHelper.FillDataTable(string.Format(SqlString.Select, count), null, DbContext, CommandKind.SqlTextNoParams);
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        DataTable dtb = Select(count);
        if (dtb == null || dtb.Rows.Count == 0)
            return result;
        result.AddRange(from DataRow row in dtb.Rows select row["Guid"].ToString());
        return result;
    }
    public bool Delete(string guid)
    {
        var parameter = new { Guid = guid };
        return (DbHelper.ExecuteNonQuery(SqlString.Delete, parameter, DbContext, CommandKind.SqlTextWithParams) > 0);
    }
} View Code Moon-SQL测试代码 public class MoonTest : ITest
{
    private readonly DB _dbHelper = DBFactory.DefaultDB;
    public bool Insert()
    {
        return (_dbHelper.ExecuteOneSql(string.Format(SqlString.InsertFormat, Guid.NewGuid(), string.Empty)) > 0);
    }
    public bool Update(string guid, string content)
    {
        return (_dbHelper.ExecuteOneSql(string.Format(SqlString.UpdateFormat, guid, content)) > 0);
    }
    public DataTable Select(int count)
    {
        return _dbHelper.GetDataTable(string.Format(SqlString.Select, count));
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        DataTable dtb = Select(count);
        if (dtb == null || dtb.Rows.Count == 0)
            return result;
        result.AddRange(from DataRow row in dtb.Rows select row["Guid"].ToString());
        return result;
    }
    public bool Delete(string guid)
    {
        return (_dbHelper.ExecuteOneSql(string.Format( SqlString.DeleteFormat,guid)) > 0);
    }
} View Code

PDF-SQL测试代码

public class PdfTest : ITest
{
    private readonly AdoHelper _dbHelper = MyDB.GetDBHelperByConnectionName("pdf");
    public bool Insert()
    {
        IDataParameter[] parameters =
        {
            new SqlParameter("@Guid",SqlDbType.VarChar,50){Value=Guid.NewGuid().ToString()},
            new SqlParameter("@Content",SqlDbType.NVarChar,500){Value=string.Empty}
        };
        return (_dbHelper.ExecuteNonQuery(SqlString.Insert, CommandType.Text, parameters) > 0);
    }
    public bool Update(string guid, string content)
    {
        IDataParameter[] parameters =
        {
            new SqlParameter("@Guid",SqlDbType.VarChar,50){Value=guid},
            new SqlParameter("@Content",SqlDbType.NVarChar,500){Value=content}
        };
        return (_dbHelper.ExecuteNonQuery(SqlString.Update, CommandType.Text, parameters) > 0);
    }
    public DataTable Select(int count)
    {
        return _dbHelper.ExecuteDataSet(string.Format(SqlString.Select, count)).Tables[0];
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        DataTable dtb = Select(count);
        if (dtb == null || dtb.Rows.Count == 0)
            return result;
        result.AddRange(from DataRow row in dtb.Rows select row["Guid"].ToString());
        return result;
    }
    public bool Delete(string guid)
    {
        IDataParameter[] parameters =
        {
            new SqlParameter("@Guid",SqlDbType.VarChar,50){Value=guid}
        };
        return (_dbHelper.ExecuteNonQuery(SqlString.Delete, CommandType.Text, parameters) > 0);
    }
} View Code

CYQ-ORM测试代码

public class CyqOrmTest : ITest
{
    public bool Insert()
    {
        bool result;
        using (MAction actiont = new MAction(TableNames.Test))
        {
            actiont.Set("Guid", Guid.NewGuid());
            result = actiont.Insert(InsertOp.None);
        }
        return result;
    }
    public bool Update(string guid, string content)
    {
        bool result;
        using (MAction actiont = new MAction(TableNames.Test))
        {
            actiont.Set("Content", content);
            result = actiont.Update("Guid='" + guid + "'");
        }
        return result;
    }
    public DataTable Select(int count)
    {
        DataTable result;
        using (MAction actiont = new MAction(TableNames.Test))
        {
            result = actiont.Select(count, "order by Guid").ToDataTable();
            //actiont.Select(count, "order by RowId");
        }
        return result;
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        DataTable dtb = Select(count);
        if (dtb == null || dtb.Rows.Count == 0)
            return result;
        result.AddRange(from DataRow row in dtb.Rows select row["Guid"].ToString());
        return result;
    }
    public bool Delete(string guid)
    {
        bool result;
        using (MAction actiont = new MAction(TableNames.Test))
        {
            result = actiont.Delete("Guid='" + guid + "'");
        }
        return result;
    }
} View Code

EF-ORM测试代码

public class EFOrmTest : ITest
{
    private readonly EFDbContext _dbContext;
    //private static readonly EFDbContext _dbContext = new EFDbContext("Conn");
    public EFOrmTest()
    {
        _dbContext = new EFDbContext("Conn");
    }
    public bool Insert()
    {
        DbSet model = _dbContext.Set();
        model.Add(new TestModel { Guid = Guid.NewGuid().ToString(), EditDate = DateTime.Now });
        _dbContext.SaveChanges();
        return true;
    }

    public bool Update(string guid, string content)
    {
        var model = _dbContext.Set().Find(guid);
        model.Content = content;
        _dbContext.Entry(model).State = EntityState.Modified;
        _dbContext.SaveChanges();
        return true;
    }

    public DataTable Select(int count)
    {
        GetModelList(count);
        return null;
    }

    public IList GetModelList(int count)
    {
        DbSet model = _dbContext.Set();
        return model.OrderBy(o => o.Guid).Take(count).ToList();
    }

    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        var list = GetModelList(count);
        if (list == null || list.Count == 0)
            return result;
        result.AddRange(list.Select(o => o.Guid));
        return result;
    }

    public bool Delete(string guid)
    {
        var model = _dbContext.Set().Find(guid);
        _dbContext.Entry(model).State = EntityState.Deleted;
        _dbContext.SaveChanges();
        return true;
    }
} View Code

Moon-ORM测试代码

public class MoonOrmTest : ITest
{
    public static void Init() { }
    public bool Insert()
    {
        return DBFactory.Add(new MoonTestModel { Guid = Guid.NewGuid().ToString() }) != DBNull.Value;
    }
    public bool Update(string guid, string content)
    {
        var model = new MoonTestModel() { Content = content };
        model.SetOnlyMark(TestTable.Guid.Equal(guid));
        DBFactory.Update(model);
        return true;
    }
    public DataTable Select(int count)
    {
        GetModelList(count);
        return null;
    }
    public IList GetModelList(int count)
    {
        //没有找到更好的查询方式
        return DBFactory.DefaultDB.GetPagedListDesc(1, count, TestTable.Guid, TestTable.Guid.NotEqual("''"));
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        var list = GetModelList(count);
        if (list == null || list.Count == 0)
            return result;
        result.AddRange(list.Select(moonTestModel => moonTestModel.Guid));
        return result;
    }
    public bool Delete(string guid)
    {
        return DBFactory.DeleteWhen(TestTable.Guid.Equal(guid)) > 0;
    }
} View Code

MySoft-ORM测试代码

public class MySoftOrmTest : ITest
{
    private static readonly DbSession DBSession = new DbSession(new MySoft.Data.SqlServer9.SqlServer9Provider(System.Configuration.ConfigurationManager.ConnectionStrings["Conn"].ConnectionString));

    public bool Insert()
    {
        return DBSession.Insert(new[] { MySoftTestModel._.Guid }, new object[] { Guid.NewGuid().ToString() }) > 0;
    }

    public bool Update(string guid, string content)
    {
        return DBSession.Update(new[] { MySoftTestModel._.Content, MySoftTestModel._.EditDate }, new object[] { content, DateTime.Now }, MySoftTestModel._.Guid == guid) > 0;
    }

    public DataTable Select(int count)
    {
        GetModelList(count);
        return null;
    }
    public IList GetModelList(int count)
    {
        return DBSession.From().OrderBy(MySoftTestModel._.Guid.Asc).GetTop(count).ToList();
    }

    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        var list = GetModelList(count);
        if (list == null || list.Count == 0)
            return result;
        result.AddRange(list.Select(o => o.Guid));
        return result;
    }

    public bool Delete(string guid)
    {
        return DBSession.Delete(MySoftTestModel._.Guid == guid) > 0;
    }
} View Code

NHibernate-ORM测试代码

public class NHibernateOrmTest : ITest
{
    private static readonly ISessionFactory SessionFactory = CreateSessionFactory();
    static NHibernateOrmTest()
    {
    }
    private static ISessionFactory CreateSessionFactory()
    {
        ISessionFactory sessionFactory;
        try
        {
            sessionFactory = Fluently.Configure()
                            .Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
                            .ConnectionString(s => s.Server(".").Database("Test")
                                .TrustedConnection()))
                            .Mappings(m =>m.FluentMappings.Add())
                            .BuildSessionFactory();
        }
        catch (Exception ex)
        {
            throw;
        }
        return sessionFactory;
    }
    public bool Insert()
    {
        using (var session = SessionFactory.OpenSession())
        {
            var model = new TestModel { Guid = Guid.NewGuid().ToString() };
            session.Save(model);
            session.Flush();
        }
        return true;
    }

    public bool Update(string guid, string content)
    {
        using (var session = SessionFactory.OpenSession())
        {
            var model = new TestModel { Guid = guid, Content = content, EditDate = DateTime.Now };
            session.Update(model);
            session.Flush();
        }
        return true;
    }

    public DataTable Select(int count)
    {
        GetModelList(count);
        return null;
    }
    public IList GetModelList(int count)
    {
        IList result;
        using (var session = SessionFactory.OpenSession())
        {
            result = session.QueryOver().OrderBy(o=>o.Guid).Asc.Take(count).List();
        }
        return result;
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        var list = GetModelList(count);
        if (list == null || list.Count == 0)
            return result;
        result.AddRange(list.Select(o => o.Guid));
        return result;
    }

    public bool Delete(string guid)
    {
        using (var session = SessionFactory.OpenSession())
        {
            var model = new TestModel { Guid = guid};
            session.Delete(model);
            session.Flush();
        }
        return true;
    }
} View Code

PDF-ORM测试代码

public class PdfOrmTest : ITest
{
    private readonly AdoHelper _dbHelper = MyDB.GetDBHelperByConnectionName("pdf");
    public bool Insert()
    {
        IDataParameter[] parameters =
        {
            new SqlParameter("@Guid",SqlDbType.VarChar,50){Value=Guid.NewGuid().ToString()},
            new SqlParameter("@Content",SqlDbType.NVarChar,500){Value=string.Empty}
        };
        return (_dbHelper.ExecuteNonQuery(SqlString.Insert, CommandType.Text, parameters) > 0);

    }
    public bool Update(string guid, string content)
    {
        PdfTestModel model = new PdfTestModel
        {
            Guid = guid,
            Content = content,
            EditDate = DateTime.Now
        };
        OQL q = OQL.From(model).Update(model.Content, model.EditDate).Where(model.Guid).END;

        return EntityQuery.ExecuteOql(q, _dbHelper) > 0;
    }
    public DataTable Select(int count)
    {
        GetModelList(count);
        return null;
    }
    public List GetModelList(int count)
    {
        PdfTestModel model = new PdfTestModel();
        OQL q = OQL.From(model).Limit(count).Select().OrderBy(model.Guid, "ASC").END;
        return EntityQuery.QueryList(q);
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        var list = GetModelList(count);
        if (list == null || list.Count == 0)
            return result;
        result.AddRange(list.Select(o => o.Guid));
        return result;
    }
    public bool Delete(string guid)
    {
        PdfTestModel model = new PdfTestModel { Guid = guid };
        OQL q = OQL.From(model).Delete().Where(model.Guid).END;
        return EntityQuery.ExecuteOql(q, _dbHelper) > 0;
    }
} View Code

XCode-ORM测试代码

public class XCodeOrmTest : ITest
{
    static XCodeOrmTest()
    {
        XCode.DataAccessLayer.DAL.ShowSQL = false;
        //XCode.DataAccessLayer.DAL.SQLPath = AppDomain.CurrentDomain.BaseDirectory;
    }
    public bool Insert()
    {
        var model = new XCodeTestModel();
        model.Guid = Guid.NewGuid().ToString();
        return model.Insert() > 0;

    }
    public bool Update(string guid, string content)
    {
        var model = XCodeTestModel.FindByGuid(guid);
        model.Content = content;
        model.EditDate = DateTime.Now;
        return model.Update() > 0;
    }
    public DataTable Select(int count)
    {
        GetModelList(count);
        return null;
    }
    public List GetModelList(int count)
    {
        return XCodeTestModel.Search(string.Empty, "Guid ASC"0, count);
    }
    public List<string> GetGuidList(int count)
    {
        List<string> result = new List<string>();
        var list = GetModelList(count);
        if (list == null || list.Count == 0)
            return result;
        result.AddRange(list.Select(o => o.Guid));
        return result;
    }
    public bool Delete(string guid)
    {
        //return XCodeTestModel.Delete(new[] { "Guid" }, new object[] { guid }) > 0;
        return XCodeTestModel.FindByGuid(guid).Delete() > 0;
    }
} View Code

测试耗时监控

/// 
/// 执行指定查询的测试,并记录测试数据
/// 

/// 线程序号
/// 执行的查询
/// instance">执行测试的组件实体
private object TestWork(object index, Actionint> execute, ITest instance)
{
    Stopwatch sw = new Stopwatch();
    string threadName = string.Format("{0:D3}", index);
    if (_showThreadWorkStatus)
        UpdateMessage(string.Format("线程{0}开始时间:{1}", threadName, DateTime.Now));
    sw.Start();
    try
    {execute(instance, (int) index);}
    catch (Exception ex)
    {UpdateMessage(string.Format("*线程{0} 执行错误,信息:{1}", threadName, ex.Message));}
    sw.Stop();
    if (_showThreadWorkStatus)
        UpdateMessage(string.Format("*线程{0}  *总耗时:{1}   *当前时间:{2}", threadName, sw.ElapsedMilliseconds, DateTime.Now));
    _waitWrite.WaitOne();
    _waitWrite.Reset();
    _workThreadCount--;
    _totalElapsed += sw.ElapsedMilliseconds;
    _workerInfo.Add(new Worker { Name = threadName, TotalElapsed = sw.ElapsedMilliseconds });

    if (_workThreadCount == 0)
    {
        UpdateMessage(string.Format("全部线程总耗时:{0} *开始时间:{1}  *结束时间:{2}", _totalElapsed, _beginTime, DateTime.Now));
        UpdateChart();
        EnableExecuteControl();
    }
    Application.DoEvents();
    UpdateThreadCountBack();
    _waitWrite.Set();
    return 0;
} View Code

测试完整逻辑代码 ,300多行,慎点。

public partial class FrmDbAccessTest : Form
{
    private string _executeType = "Insert";//测试查询类型
    private string _testLibClassPath = "DbAccessLibTest.Test.ClownFishTest";//测试组件类路径
    private long _totalElapsed;//总耗时
    private int _workThreadCount;//工作线程数
    private int _threadCountCreated, _threadCountBack;
    private int _executeCount;//执行查询次数(返回行数)
    private bool _showThreadWorkStatus;
    private Dictionary<int, List<string>> _guidList;//执行删除和修改时,预先取回的主键guid集合,按照每个线程序号分组分配
    private List _workerInfo;//测试工作线程信息,主要用于图表数据显示
    private ITest _testInstance;//用于准备执行删除、修改的guid集合
    private DateTime _beginTime;//测试开始的时间
    private readonly AutoResetEvent _waitWrite = new AutoResetEvent(true);//编辑总耗时等全局信息的信号灯
    private CancellationTokenSource _taskCancelToken;
    private readonly Assembly _self = Assembly.Load("数据访问组件测试");
    public FrmDbAccessTest()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        _workerInfo = new List();
        chartMain.Series[0].XValueMember = "Name";
        chartMain.Series[0].YValueMembers = "TotalElapsed";
        chartMain.DataSource = _workerInfo;
    }
    /// 
    
/// 执行测试
    
/// 

    private void btnExecute_Click(object sender, EventArgs e)
    {
        //初始化数据
        _workThreadCount = (int)nuWorkThreadCount.Value;
        _executeCount = (int)nuExecuteCount.Value;
        _totalElapsed = 0;
        _workerInfo = new List();
        _testLibClassPath = "DbAccessLibTest.Test." + cmbTestLib.Text;
        _testInstance = (ITest)_self.CreateInstance(_testLibClassPath);
        _beginTime = DateTime.Now;
        UpdateMessage(string.Format("测试开始时间:{0}", DateTime.Now));
        UpdateMessage(string.Format("  启动线程数:{0}", _workThreadCount));
        UpdateMessage(string.Format("  执行操作数:{0}", _executeCount));
        btnExecute.Enabled = false;
        nuThreadCountBack.Value = _threadCountBack = 0;
        nuThreadCountCreated.Value = _threadCountCreated = 0;
        _showThreadWorkStatus = ckbShowThreadStatus.Checked;
        ckbShowThreadStatus.Enabled = false;

        new Thread(TestMain).Start();
    }

    private void TestMain()
    {
        try
        {
            UpdateMessage(string.Format("数据准备开始:{0}", DateTime.Now));
            Actionint> testExecute = GetExecuteUse();
            UpdateMessage(string.Format("数据准备结束:{0}", DateTime.Now));
            int createCount = _workThreadCount;
            UpdateMessage(string.Format("开始创建线程:{0}", DateTime.Now));
            _taskCancelToken = new CancellationTokenSource();
            for (int index = 0; index < createCount; index++)
            {
                if (IsDisposed)
                    return;//防止重启程序时,仍然不断创建线程
                if (rdbThreadPool.Checked)
                    UseThreadPool(index, testExecute);
                else if (rdbThread.Checked)
                    UseThread(index, testExecute);
                else
                {
                    if (!UseTask(index, testExecute))
                        return;//如果已经重启程序,则跳出
                }
                Thread.Sleep(50);
                UpdateThreadCountCreated();
            }
            UpdateMessage(string.Format("创建线程完毕:{0}", DateTime.Now));
        }
        catch (Exception ex)
        {
            UpdateMessage(ex.Message);
        }
    }
    private void UseThreadPool(int index, Actionint> testExecute)
    {
        ThreadPool.QueueUserWorkItem(
                                    threadIndex =>
                                    TestWork(threadIndex, testExecute
                                    , (ITest)_self.CreateInstance(_testLibClassPath)), index);
    }
    private void UseThread(int index, Actionint> testExecute)
    {
        new Thread(
                threadIndex =>
                TestWork(threadIndex, testExecute
                , (ITest)_self.CreateInstance(_testLibClassPath)))
                .Start(index);
    }
    private bool UseTask(int index, Actionint> testExecute)
    {
        var task = new Task<object>
            (
                threadIndex => TestWork(threadIndex, testExecute, (ITest)_self.CreateInstance(_testLibClassPath))
                , index
                , _taskCancelToken.Token
            );
        if (_taskCancelToken.IsCancellationRequested)
            return false;
        task.Start();
        return true;
    }
    /// 
    
/// 执行指定查询的测试,并记录测试数据
    
/// 

    
/// 线程序号
    
/// 执行的查询
    
/// 执行测试的组件实体
    private object TestWork(object index, Actionint> execute, ITest instance)
    {
        Stopwatch sw = new Stopwatch();
        string threadName = string.Format("{0:D3}", index);
        if (_showThreadWorkStatus)
            UpdateMessage(string.Format("线程{0}开始时间:{1}", threadName, DateTime.Now));
        sw.Start();
        try
        {execute(instance, (int) index);}
        catch (Exception ex)
        {UpdateMessage(string.Format("*线程{0} 执行错误,信息:{1}", threadName, ex.Message));}
        sw.Stop();
        if (_showThreadWorkStatus)
            UpdateMessage(string.Format("*线程{0}  *总耗时:{1}   *当前时间:{2}", threadName, sw.ElapsedMilliseconds, DateTime.Now));
        _waitWrite.WaitOne();
        _waitWrite.Reset();
        _workThreadCount--;
        _totalElapsed += sw.ElapsedMilliseconds;
        _workerInfo.Add(new Worker { Name = threadName, TotalElapsed = sw.ElapsedMilliseconds });

        if (_workThreadCount == 0)
        {
            UpdateMessage(string.Format("全部线程总耗时:{0} *开始时间:{1}  *结束时间:{2}", _totalElapsed, _beginTime, DateTime.Now));
            UpdateChart();
            EnableExecuteControl();
        }
        Application.DoEvents();
        UpdateThreadCountBack();
        _waitWrite.Set();
        return 0;
    }
    #region 执行查询

    private void ExecuteInsert(ITest instance, int threadIndex)
    {
        for (int i = 0; i < _executeCount; i++)
            instance.Insert();
    }

    private void ExecuteUpdate(ITest instance, int threadIndex)
    {
        foreach (string guid in _guidList[threadIndex])
            instance.Update(guid, string.Format("测试修改 **线程:{0}**组件:{1}**时间:{2}", threadIndex, instance.GetType(), DateTime.Now));
    }

    private void ExecuteDelete(ITest instance, int threadIndex)
    {
        foreach (string guid in _guidList[threadIndex])
            instance.Delete(guid);
    }

    private void ExecuteSelect(ITest instance, int threadIndex)
    {
        instance.Select(_executeCount);
    }

    #endregion

    /// 
    
/// 获取测试的操作,如果是删除和更新,则先准备数据
    
/// 

    
/// 
    private Actionint> GetExecuteUse()
    {
        switch (_executeType)
        {
            case "Insert":
                return ExecuteInsert;
            case "Delete":
                AssignGuid(); return ExecuteDelete;
            case "Update":
                AssignGuid(); return ExecuteUpdate;
            case "Select":
                return ExecuteSelect;
        }
        throw new Exception("程序异常:GetExecute");
    }
    /// 
    
/// 获取删除或者更新需要的guid集合,并分配给各个线程
    
/// 

    private void AssignGuid()
    {
        var list = _testInstance.GetGuidList(_workThreadCount * _executeCount);
        _guidList = new Dictionary<int, List<string>>(_workThreadCount);
        for (int i = 0; i < _workThreadCount; i++)
            _guidList.Add(i, new List<string>());
        for (int i = 0; i < list.Count; i++)
        {
            int index = i % _workThreadCount;
            _guidList[index].Add(list[i]);
        }
    }
    /// 
    
/// 更新图表
    
/// 

    private void UpdateChart()
    {
        if (IsDisposed)
            return;
        if (InvokeRequired)
            BeginInvoke(new MethodInvoker(UpdateChart));
        else
        {
            if (_workerInfo.Count > 10)
                chartMain.Series[0].Label = string.Empty;
            _workerInfo.Sort();
            chartMain.DataSource = _workerInfo;
            chartMain.ResetAutoValues();
        }
    }
    /// 
    
/// 更新信息
    
/// 

    
/// 
    private void UpdateMessage(string msg)
    {
        if (IsDisposed)
        {
            return;
        }
        if (InvokeRequired)
            BeginInvoke(new MethodInvoker(() => UpdateMessage(msg)));
        else
        {
            rtxtMessage.AppendText(msg + "\n");
            rtxtMessage.Select(rtxtMessage.Text.Length - 11);
            rtxtMessage.ScrollToCaret();
        }
    }
    /// 
    
/// 更新已创建线程数
    
/// 

    private void UpdateThreadCountCreated()
    {
        if (IsDisposed)
            return;
        if (InvokeRequired)
            BeginInvoke(new MethodInvoker(UpdateThreadCountCreated));
        else
            nuThreadCountCreated.Value = _threadCountCreated = (int)nuThreadCountCreated.Value + 1;
    }
    /// 
    
/// 更新返回线程数
    
/// 

    private void UpdateThreadCountBack()
    {
        if (IsDisposed)
            return;
        if (InvokeRequired)
            BeginInvoke(new MethodInvoker(UpdateThreadCountBack));
        else
            nuThreadCountBack.Value = _threadCountBack = (int)nuThreadCountBack.Value + 1;
    }

    /// 
    
/// 启用执行按钮
    
/// 

    private void EnableExecuteControl()
    {
        if (IsDisposed)
            return;
        Invoke(new MethodInvoker(() =>
        {
            btnExecute.Enabled = true;
            ckbShowThreadStatus.Enabled = true;
        }));
    }
    private void rdbExecute_CheckedChanged(object sender, EventArgs e)
    {
        RadioButton rdb = sender as RadioButton;
        if (rdb == null)
            throw new Exception("程序异常:rdbExecute_CheckedChanged");
        if (rdb.Checked)
            _executeType = rdb.Text;
    }

    private void btnAnalysis_Click(object sender, EventArgs e)
    {
        //暂时没有实现
    }
    private void btnTruncateTable_Click(object sender, EventArgs e)
    {
        if (MessageBox.Show("确定要清空整个表吗""提示", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes)
        {
            btnTruncateTable.Enabled = false;
            new ClownFishTest().TruncateTable();
            UpdateMessage("表已清空 - " + DateTime.Now);
            btnTruncateTable.Enabled = true;
        }
    }

    private void btnThreadInfo_Click(object sender, EventArgs e)
    {
        UpdateMessage(string.Format("线程数:{0}", _workThreadCount));
    }

    private void btnRestartForm_Click(object sender, EventArgs e)
    {
        DialogResult = DialogResult.OK;
        if (rdbTask.Checked)
            _taskCancelToken.Cancel(true);
        Close();
        Dispose();
    }
} View Code

 
到底是选择ORM而不写Sql,还是 为了追求性能,而避开ORM,就看自己的情况来取舍了。

选择一个组件的时候,可以考虑这几方面:稳定性、性能、易用性、是否保持更新、是否有较好的文档手册、使用者社区怎么样、是否开源

上面提供的组件测试代码也可以看到这些组件的代码风格,喜欢语法糖的不妨好好看看,到底更喜欢哪种风格

综合考虑选择。

 

各组件地址
ClownFish:http://www.cnblogs.com/fish-li/ 【不开源】仅此一个是非ORM的。
CYQ:http://www.cnblogs.com/cyq1162/ 【逐版本开源】
EF: https://entityframework.codeplex.com/ 【开源】
Moon:http://www.cnblogs.com/humble/ 【不开源】
MySoft:http://www.cnblogs.com/maoyong/archive/2010/03/01/1675730.html 【逐版本开源】
NHibernate:http://nhforge.org/ 【开源】
PDF:http://home.cnblogs.com/u/bluedoctor/ 【开源】
XCode:http://xcode.codeplex.com/ 【开源】
希望更多的园友分享或开源自己所能知道的心爱的数据访问组件。

 

小广告:广州有工作机会的,烦请推荐。

发表评论
用户名: 匿名