このテストアプリケーションを同時に実行するための最良の方法は何ですか?
プログラムが終了すると、コンソールアプリケーションは従業員数をとして出力します4057
。これは、従業員のカウント回数を増やすスレッドがある20000
ためです。20
1000
Program.cs
using System;
using System.Data;
using System.Diagnostics;
using System.Threading.Tasks;
using DataAccess;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace NhibernatePlayground
{
internal class Program
{
private static ISessionFactory _sessionFactory;
private static Configuration _configuration;
private static int TotalThreadCount = 20;
private static int LoopCount = 1000;
private static void Main(string[] args)
{
_configuration = BuildConfiguration();
var se = new SchemaExport(_configuration);
se.Drop(true, true);
se.Create(false, true);
_sessionFactory = _configuration.BuildSessionFactory();
int companyId = Seed();
Stopwatch sw = new Stopwatch();
sw.Start();
Task[] tasks = new Task[TotalThreadCount];
for (int i = 0; i < TotalThreadCount; i ++)
{
tasks[i] = Task.Factory.StartNew(() => IncreaseEmployeeCount(LoopCount, companyId));
}
//Block until all tasks complete.
Task.WaitAll(tasks);
sw.Stop();
Console.WriteLine("Employee Count: " + GetEmployeeCount(companyId));
Console.WriteLine("Total Milliseconds: " + sw.ElapsedMilliseconds);
Console.ReadKey();
}
private static Configuration BuildConfiguration()
{
Configuration configuration = new Configuration();
configuration.Configure(); // A
configuration.AddAssembly(typeof (Company).Assembly); // B
return configuration;
}
private static void IncreaseEmployeeCount(int count, int companyId)
{
for (int i = 0; i < count; i++)
{
using (ISession _session = _sessionFactory.OpenSession())
{
using (ITransaction _transaction = _session.BeginTransaction())
{
var company = _session.Get<Company>(companyId);
company.EmployeeCount++;
_session.Save(company);
_transaction.Commit();
}
}
}
}
private static int Seed()
{
using (ISession _session = _sessionFactory.OpenSession())
{
using (ITransaction _transaction = _session.BeginTransaction())
{
Company company = new Company
{
CompanyName = "Angus"
};
_session.Save(company);
_transaction.Commit();
return company.Id;
}
}
}
private static int GetEmployeeCount(int companyId)
{
using (ISession _session = _sessionFactory.OpenSession())
{
using (ITransaction _transaction = _session.BeginTransaction())
{
Company company = _session.Get<Company>(companyId);
return company.EmployeeCount;
}
}
}
}
}
Company.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataAccess" namespace="DataAccess" >
<class name="Company">
<id name="Id">
<generator class="hilo" />
</id>
<property name="IsActive" />
<property name="CompanyName" />
<property name="EmployeeCount" />
<set name="Users" table="Users_Companies" cascade="none">
<key column="CompanyId"/>
<many-to-many column="UserId" class="UserProfile" />
</set>
</class>
</hibernate-mapping>
Company.cs
using Iesi.Collections.Generic;
namespace DataAccess
{
public class Company : Entity<int>
{
public Company()
{
//it's not the best practice to initialize virtual properties in constructor but we're controlling
//the inheritance in this so doing this should be fine
// http://stackoverflow.com/a/469577/89605
Users = new HashedSet<UserProfile>();
}
public Company(string name)
: this()
{
CompanyName = name;
IsActive = true;
}
public virtual string CompanyName { set; get; }
public virtual bool IsActive { set; get; }
public virtual ISet<UserProfile> Users { set; get; }
public virtual int EmployeeCount { set; get; }
public virtual void CopyTo(Company target)
{
target.CompanyName = CompanyName;
target.IsActive = IsActive;
}
}
}