簡體   English   中英

休眠和並發

[英]Nhibernate and Concurrency

使該測試應用程序同時運行的最佳方法是什么?

我的程序完成后,控制台應用程序將雇員計數打印為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;
        }
    }
}

在讀取對象時,您需要在數據庫中獲取寫鎖。 探索Get()或ISession.Lock()方法的鎖定模式參數。 這將是悲觀鎖定,適用於這種情況(頻繁寫入同一數據)。 另一種選擇是樂觀鎖定,當很少寫入相同數據時,這種方法最有效。 為此,請探索NHibernate的<version>映射元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM