0

このテストアプリケーションを同時に実行するための最良の方法は何ですか?

プログラムが終了すると、コンソールアプリケーションは従業員数をとして出力します4057。これは、従業員のカウント回数を増やすスレッドがある20000ためです。201000

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;
        }
    }
}
4

1 に答える 1

0

オブジェクトの読み取り中に、データベースで書き込みロックを取得する必要があります。Get() または ISession.Lock() メソッドのロック モード パラメーターを調べます。これは悲観的ロックであり、このようなシナリオ (同じデータへの頻繁な書き込み) に適しています。代替手段は楽観的ロックです。これは、同じデータへの書き込みが頻繁に行われない場合に最適です。そのためには、NHibernate の <version> マッピング要素を調べてください。

于 2013-03-22T16:56:48.017 に答える