0

使此测试应用程序同时运行的最佳方法是什么?

当我的程序完成后,控制台应用程序将员工人数打印为4057. 这应该是20000因为我有20线程增加员工计数1000时间。

程序.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;
                }
            }
        }
    }
}

公司.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>

公司.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 回答