
â ãœãŒã¹ã³ãŒãã®ããŠã³ããŒã-962 Kb
äŸåæ§æ³šå ¥ã¯ãããŒãã³ãŒãã£ã³ã°ãããäŸåé¢ä¿ãåé€ããããå®è¡æããã³ã³ã³ãã€ã«æã«ããããå€æŽãããã§ãããœãããŠã§ã¢éçºãã¿ãŒã³ã§ã[1] ã
ãªããžããªã¯ããã¡ã€ã³ãšããŒã¿è¡šç€ºå±€ã®éã®äžéäœã§ãããç¹å¥ãªã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠãã¡ã€ã³ãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ããŸã[2] ã
äœæ¥ãŠãããã¯ãã¢ããªã±ãŒã·ã§ã³ã®ãã©ã³ã¶ã¯ã·ã§ã³æ©èœãå®çŸ©ããã³ç®¡çããããã«äœ¿çšããããã¿ãŒã³ã§ã[4] ã
ãšã³ãã£ãã£ãšäœæ¥ãŠãããã®çŽ¹ä»ã«ã€ããŠã¯ãå€ãã®èšäºãã¬ãã¹ã³ãããã³ãã®ä»ã®ãªãœãŒã¹ããããŸãã®ã§ããããã«ã€ããŠã¯å®çŸ©ããŸããã ãã®èšäºã¯ãåŸã§èª¬æããå°é£ã解決ããããšã«å°å¿µããŠããŸãã
é£ãã
ããŒã¿é§ååã¢ããªã±ãŒã·ã§ã³ã®éçºã¯ãããã€ãã®ååã«åŸãå¿ èŠããããŸãã ç§ã話ãããã®ã¯ããããã®ååã«ã€ããŠã§ãã
æ¥ç¶ãééããæ¹æ³
ãã¡ãããæ¥ç¶ã¯ããŒã¿ããŒã¹ã¬ãã«ïŒãªããžããªå ïŒã§æé©ã«ç®¡çãããŸãã ããšãã°ããªããžããªã¡ãœãããžã®ãã¹ãŠã®åŒã³åºãã§ãæ¥ç¶ãéããããŒã¿ããŒã¹ã§ã³ãã³ããå®è¡ããæ¥ç¶ãéããããšãã§ããŸãã ããããåããªããžããªå ã®ç°ãªãã¡ãœãããŸãã¯ç°ãªããªããžããªã®ç°ãªãã¡ãœããã«åãæ¥ç¶ã䜿çšããå¿ èŠãããå Žåããã®ãªãã·ã§ã³ã¯éå¹çã«ãªããŸãïŒç°ãªããªããžããªã®ã¡ãœããã䜿çšãããã©ã³ã¶ã¯ã·ã§ã³ãèããŠãã ããïŒã
ïŒASP.NET MVCãŸãã¯Webãã©ãŒã ã䜿çšããŠïŒãµã€ããäœæãããšããApplication_BeginRequestã䜿çšããŠæ¥ç¶ãéããApplication_EndRequestã䜿çšããŠæ¥ç¶ãéããããšãã§ããŸãã ãããããã®ã¢ãããŒãã«ã¯æ¬ ç¹ããããŸãã
- ãã¹ãŠã®ãªã¯ãšã¹ããããŒã¿ããŒã¹ã䜿çšããŠããããã§ã¯ãªãå Žåã§ããããŒã¿ããŒã¹ã¯ãªã¯ãšã¹ãããšã«ééãããŸãã æ¥ç¶ã䜿çšãããŠããªãå Žåã§ããæ¥ç¶ã¯ããŒã«ããååŸãããããšãããããŸãã
- ããŒã¿ããŒã¹ã¯ã¯ãšãªã®æåã«éããæåŸã«éããŸãã ãã ããèŠæ±ãé·ãããå ŽåããããããŒã¿ããŒã¹æäœã«ãããæéããããã§ãããããæ¥ç¶ããŒã«ã®äœ¿çšãéå¹ççã«ãªããŸãã
äžèšã®å°é£ã¯ããªãã«ã¯ããããªããšãããããŸããããç§ã«ãšã£ãŠã¯å€§ããªåé¡ã§ãã ãããããµã€ããéçºããããã°ããã®éããŒã¿ããŒã¹ã䜿çšããå€ãã®ã¹ã¬ãããèµ·åããWindowsãµãŒãã¹ãéçºãããã©ãã§ããããã ãã®å Žåãã©ãã§æ¥ç¶ãéãããéãããããŸããïŒ
ãã©ã³ã¶ã¯ã·ã§ã³ã管çããæ¹æ³
ã¢ããªã±ãŒã·ã§ã³ïŒã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ãšåæ§ïŒãããŒã¿ããŒã¹ãæäœãããšãã«ãã©ã³ã¶ã¯ã·ã§ã³ã䜿çšããå Žåããã®å Žåããã©ã³ã¶ã¯ã·ã§ã³ãã©ãã§éå§ãã³ãããããŸãã¯ããŒã«ããã¯ããå¿ èŠããããŸããïŒ ãªããžããªã¡ãœããã§ãããè¡ãããšã¯ã§ããŸããããã©ã³ã¶ã¯ã·ã§ã³ã«ã¯ããªããžããªã¡ãœãããžã®ããŸããŸãªåŒã³åºããå«ããããšãã§ããŸãã ãããã£ãŠããããã®æäœã¯ãã¹ãŠãã¡ã€ã³ã¬ã€ã€ãŒã§å®è¡ã§ããŸãã ãããããã®ã¢ãããŒãã«ã¯æ¬ ç¹ããããŸãã
- ãã¡ã€ã³å±€ã«ã¯ãããŒã¿ããŒã¹åºæã®ã³ãŒããå«ãŸããŠããŸãããããã¯åäžã®çŸ©åãšãã«ãã¬ãã«è¡šçŸã®äœ¿çšã®ååã«éåããŠããŸãã
- ãã®ã¢ãããŒãã¯ããã¡ã€ã³ã¬ã€ã€ãŒã®åã¡ãœããã®ãã©ã³ã¶ã¯ã·ã§ã³ããžãã¯ãè€è£œããŸãã
äžã§è¿°ã¹ãããã«ãApplication_BeginRequestãšApplication_EndRequestã䜿çšããŠãã©ã³ã¶ã¯ã·ã§ã³ã管çã§ããŸãã ããã§ãåãåé¡ãçºçããŸããäžèŠãªãã©ã³ã¶ã¯ã·ã§ã³ãéå§ãŸãã¯ã³ãããããŸãã ããã«ããšã©ãŒãä¿®æ£ããåŸããããã®äžéšãããŒã«ããã¯ããå¿ èŠããããŸãã
Webãµã€ãã§ã¯ãªãã¢ããªã±ãŒã·ã§ã³ãéçºããŠããå Žåããã©ã³ã¶ã¯ã·ã§ã³ãéå§ãã³ããããããã³ããŒã«ããã¯ããé©åãªå ŽæãèŠã€ããã®ã¯ç°¡åã§ã¯ãããŸããã
ãããã£ãŠãæ¬åœã«å¿ èŠãªãšãã«ãã©ã³ã¶ã¯ã·ã§ã³ãéå§ãããã¹ãŠã®æäœãæåããå Žåã«èšé²ããããããã®æäœã倱æããå Žåã«ã®ã¿ããŒã«ããã¯ããã®ãæåã§ãã ãã®ååã«åºã¥ããŠãç§ã¯ããã«æå°ãããŸãã
å®è£
ç§ã®ã¢ããªã±ãŒã·ã§ã³ã¯ãASP.NET MVCïŒWebãã¬ãŒã ã¯ãŒã¯ãšããŠïŒãSQL ServerïŒDBMSãšããŠïŒãNHibernateïŒORMãšããŠïŒãCastle WindsorïŒäŸåæ§æ³šå ¥ã³ã³ãããŒãšããŠïŒã䜿çšããŠäœæãããé»è©±åž³ã§ãã
ãšã³ãã£ãã£
ç§ã®å®è£ ã§ã¯ããšã³ãã£ãã£ã¯ããŒã¿ããŒã¹å ã®ããŒãã«ãšã³ããªã«å€æãããŸãã ãªããžã§ã¯ãæåèšèšã®ãšã³ãã£ãã£ã¯ã äžæã®èå¥åãæã€æ°žç¶ãªããžã§ã¯ãã§ãã ãã®å Žåããã¹ãŠã®ãšã³ãã£ãã£ã¯ä»¥äžã®Entityã¯ã©ã¹ãã掟çããŸãã
public interface IEntity<TPrimaryKey> { TPrimaryKey Id { get; set; } } public class Entity<TPrimaryKey> : IEntity<TPrimaryKey> { public virtual TPrimaryKey Id { get; set; } }
ãšã³ãã£ãã£ã«ã¯äžæã®èå¥åããããŸããããã¯äž»ããŒã§ãããç°ãªãã¿ã€ãïŒintãlongãguidãªã©ïŒãæã€ããšãã§ããŸãã ãããã£ãŠãæã ã¯ãžã§ããªãã¯ã¯ã©ã¹ãæ±ã£ãŠãããPeopleãPhoneãCityãªã©ã®ãšã³ãã£ãã£ã¯ãããã掟çããŠããŸãã Peopleã¯ã©ã¹ã®å®çŸ©ã¯æ¬¡ã®ããã«ãªããŸãã
public class Person : Entity<int> { public virtual int CityId { get; set; } public virtual string Name { get; set; } public virtual DateTime BirthDay { get; set; } public virtual string Notes { get; set; } public virtual DateTime RecordDate { get; set; } public Person() { Notes = ""; RecordDate = DateTime.Now; } }
ã芧ã®ãšãããPersonã®äž»ããŒã¯intãšããŠå®çŸ©ãããŠããŸãã
ãšã³ãã£ãã£å€æ
EntityãNHibernateãã¬ãŒã ã¯ãŒã¯ãªã©ã®ãªããžã§ã¯ããªã¬ãŒã·ã§ãã«ãããã³ã°ããŒã«ã§ã¯ããšã³ãã£ãã£ãããŒã¿ããŒã¹ããŒãã«ã«å€æããå®çŸ©ãå¿ èŠã§ãã ãããå®è£ ããã«ã¯å€ãã®æ¹æ³ããããŸãã ããšãã°ãNHibernate Fluent APIã䜿çšããŸããã 以äžã®Peopleãšã³ãã£ãã£ã®äŸã«ç€ºãããã«ããã¹ãŠã®ãšã³ãã£ãã£ã®å€æã¯ã©ã¹ãå®çŸ©ããå¿ èŠããããŸãã
public class PersonMap : ClassMap<Person> { public PersonMap() { Table("People"); Id(x => x.Id).Column("PersonId"); Map(x => x.CityId); Map(x => x.Name); Map(x => x.BirthDay); Map(x => x.Notes); Map(x => x.RecordDate);
ãªããžããªïŒDBã¬ãã«ïŒ
ãªããžããªã䜿çšããŠããŒã¿ããŒã¹ã¬ãã«ãäœæããããŒã¿ã¢ã¯ã»ã¹ã®ããžãã¯ãäžäœã¬ãã«ããåé¢ããŸãã ãªããžããªã¯ã©ã¹ã¯éåžžããšã³ãã£ãã£ãŸãã¯éçŽïŒãšã³ãã£ãã£ã®ã°ã«ãŒãïŒããšã«äœæãããŸãã ãšã³ãã£ãã£ããšã«ãªããžããªãäœæããŸããã æåã«ããã¹ãŠã®ãªããžããªã¯ã©ã¹ã«ãã£ãŠå®è£ ãããå¿ èŠãããã€ã³ã¿ãŒãã§ã€ã¹ãå®çŸ©ããŸããã
/// <summary> /// This interface must be implemented by all repositories to ensure UnitOfWork to work. /// </summary> public interface IRepository { } /// <summary> /// This interface is implemented by all repositories to ensure implementation of fixed methods. /// </summary> /// <typeparam name="TEntity">Main Entity type this repository works on</typeparam> /// <typeparam name="TPrimaryKey">Primary key type of the entity</typeparam> public interface IRepository<TEntity, TPrimaryKey> : IRepository where TEntity : Entity<TPrimaryKey> { /// <summary> /// Used to get a IQueryable that is used to retrive entities from entire table. /// </summary> /// <returns>IQueryable to be used to select entities from database</returns> IQueryable<TEntity> GetAll(); /// <summary> /// Gets an entity. /// </summary> /// <param name="key">Primary key of the entity to get</param> /// <returns>Entity</returns> TEntity Get(TPrimaryKey key); /// <summary> /// Inserts a new entity. /// </summary> /// <param name="entity">Entity</param> void Insert(TEntity entity); /// <summary> /// Updates an existing entity. /// </summary> /// <param name="entity">Entity</param> void Update(TEntity entity); /// <summary> /// Deletes an entity. /// </summary> /// <param name="id">Id of the entity</param> void Delete(TPrimaryKey id); }
ãããã£ãŠããã¹ãŠã®ãªããžããªã¯ã©ã¹ã¯äžèšã®ã¡ãœãããå®è£ ããå¿ èŠããããŸãã ãã ããNHibernateã«ã¯ããããã®ã¡ãœããã®å®è£ ãã»ãŒåãã§ãã åãããžãã¯ããã¹ãŠã®ãªããžããªã«é©çšããã«ããã¹ãŠã®ãªããžããªã®åºæ¬ã¯ã©ã¹ãå®çŸ©ã§ããããšãããããŸããã NhRepositoryBaseã®å®çŸ©ã¯æ¬¡ã®ãšããã§ãã
/// <summary> /// Base class for all repositories those uses NHibernate. /// </summary> /// <typeparam name="TEntity">Entity type</typeparam> /// <typeparam name="TPrimaryKey">Primary key type of the entity</typeparam> public abstract class NhRepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : Entity<TPrimaryKey> { /// <summary> /// Gets the NHibernate session object to perform database operations. /// </summary> protected ISession Session { get { return NhUnitOfWork.Current.Session; } } /// <summary> /// Used to get a IQueryable that is used to retrive object from entire table. /// </summary> /// <returns>IQueryable to be used to select entities from database</returns> public IQueryable<TEntity> GetAll() { return Session.Query<TEntity>(); } /// <summary> /// Gets an entity. /// </summary> /// <param name="key">Primary key of the entity to get</param> /// <returns>Entity</returns> public TEntity Get(TPrimaryKey key) { return Session.Get<TEntity>(key); } /// <summary> /// Inserts a new entity. /// </summary> /// <param name="entity">Entity</param> public void Insert(TEntity entity) { Session.Save(entity); } /// <summary> /// Updates an existing entity. /// </summary> /// <param name="entity">Entity</param> public void Update(TEntity entity) { Session.Update(entity); } /// <summary> /// Deletes an entity. /// </summary> /// <param name="id">Id of the entity</param> public void Delete(TPrimaryKey id) { Session.Delete(Session.Load<TEntity>(id)); } }
ã»ãã·ã§ã³ããããã£ã¯ãçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã®æ£ããSessionãªããžã§ã¯ããåãåãNhUnitOfWork.Current.Sessionããã»ãã·ã§ã³ãªããžã§ã¯ãïŒNHibernateã®ããŒã¿ããŒã¹æ¥ç¶ãªããžã§ã¯ãïŒãååŸããããã«äœ¿çšãããŸãã ãããã£ãŠãæ¥ç¶ãŸãã¯ãã©ã³ã¶ã¯ã·ã§ã³ãéãããéãããããæ¹æ³ã決å®ããå¿ èŠã¯ãããŸããã ããã«ããã®ã¡ã«ããºã ã®èª¬æã«ã€ããŠè©³ãã説æããŸãã
ãã¹ãŠã®ãªããžããªã«å¯ŸããŠããã¹ãŠã®CRUDæäœãããã©ã«ãã§å®è£ ãããŠããŸãã ããã§ããšã³ããªãéžæãæŽæ°ãåé€ã§ããPersonRepositoryãäœæã§ããŸãã ãããè¡ãã«ã¯ã次ã®ããã«2ã€ã®åã宣èšããŸãã
public interface IPersonRepository : IRepository<Person, int> { } public class NhPersonRepository : NhRepositoryBase<Person, int>, IPersonRepository { }
åãããšãPhoneããã³Cityãšã³ãã£ãã£ã«å¯ŸããŠãå®è¡ã§ããŸãã ç¹å¥ãªãªããžããªã¡ãœãããè¿œå ããå¿ èŠãããå Žåã察å¿ãããšã³ãã£ãã£ã®ãªããžããªã§ãããè¡ãããšãã§ããŸãã ããšãã°ãç¹å®ã®äººã®é»è©±ãåé€ã§ããããã«ãPhoneRepositoryã«æ°ããã¡ãœãããè¿œå ããŸãã
public interface IPhoneRepository : IRepository<Phone, int> { /// <summary> /// Deletes all phone numbers for given person id. /// </summary> /// <param name="personId">Id of the person</param> void DeletePhonesOfPerson(int personId); } public class NhPhoneRepository : NhRepositoryBase<Phone, int>, IPhoneRepository { public void DeletePhonesOfPerson(int personId) { var phones = GetAll().Where(phone => phone.PersonId == personId).ToList(); foreach (var phone in phones) { Session.Delete(phone); } } }
äœæ¥åäœ
äœæ¥åäœã¯ãã¢ããªã±ãŒã·ã§ã³ã®ãã©ã³ã¶ã¯ã·ã§ã³æ©èœãå®çŸ©ããã³ç®¡çããããã«äœ¿çšãããŸãã ãŸããIUnitOfWorkã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ããå¿ èŠããããŸãã
/// <summary> /// Represents a transactional job. /// </summary> public interface IUnitOfWork { /// <summary> /// Opens database connection and begins transaction. /// </summary> void BeginTransaction(); /// <summary> /// Commits transaction and closes database connection. /// </summary> void Commit(); /// <summary> /// Rollbacks transaction and closes database connection. /// </summary> void Rollback(); }
NHibernateã®IUnitOfWorkã®å®è£ ã以äžã«ç€ºããŸãã
/// <summary> /// Implements Unit of work for NHibernate. /// </summary> public class NhUnitOfWork : IUnitOfWork { /// <summary> /// Gets current instance of the NhUnitOfWork. /// It gets the right instance that is related to current thread. /// </summary> public static NhUnitOfWork Current { get { return _current; } set { _current = value; } } [ThreadStatic] private static NhUnitOfWork _current; /// <summary> /// Gets Nhibernate session object to perform queries. /// </summary> public ISession Session { get; private set; } /// <summary> /// Reference to the session factory. /// </summary> private readonly ISessionFactory _sessionFactory; /// <summary> /// Reference to the currently running transcation. /// </summary> private ITransaction _transaction; /// <summary> /// Creates a new instance of NhUnitOfWork. /// </summary> /// <param name="sessionFactory"></param> public NhUnitOfWork(ISessionFactory sessionFactory) { _sessionFactory = sessionFactory; } /// <summary> /// Opens database connection and begins transaction. /// </summary> public void BeginTransaction() { Session = _sessionFactory.OpenSession(); _transaction = Session.BeginTransaction(); } /// <summary> /// Commits transaction and closes database connection. /// </summary> public void Commit() { try { _transaction.Commit(); } finally { Session.Close(); } } /// <summary> /// Rollbacks transaction and closes database connection. /// </summary> public void Rollback() { try { _transaction.Rollback(); } finally { Session.Close(); } } }
éçããããã£Currentã¯ãã¯ã©ã¹å šäœã«ãšã£ãŠéèŠã§ãã ThreadStaticãšããŠããŒã¯ããã_currentãã£ãŒã«ããåãåããæ§æããŸãã ããããã°ãåãã¹ã¬ããã§åãäœæ¥åäœãªããžã§ã¯ãã䜿çšã§ããŸãã ããã¯ãè€æ°ã®ãªããžã§ã¯ããåãæ¥ç¶ãŸãã¯ãã©ã³ã¶ã¯ã·ã§ã³ãå ±æã§ããããšãæå³ããŸãã æåŸã«ãã¡ãœãããããŒã¯ããããã«äœ¿çšãããå±æ§ãå®çŸ©ããŸããããã¯ãã©ã³ã¶ã¯ã·ã§ã³åã§ããå¿ èŠããããŸãã
/// <summary> /// This attribute is used to indicate that declaring method is transactional (atomic). /// A method that has this attribute is intercepted, a transaction starts before call the method. /// At the end of method call, transaction is commited if there is no exception, othervise it's rolled back. /// </summary> [AttributeUsage(AttributeTargets.Method)] public class UnitOfWorkAttribute : Attribute { }
ç¹å®ã®ã¡ãœããããã©ã³ã¶ã¯ã·ã§ã³åã§ããå ŽåãUnitOfWorkå±æ§ã§ããŒã¯ããå¿ èŠããããŸãã 次ã«ã以äžã«ç€ºãããã«ãäŸåæ§æ³šå ¥ã䜿çšããŠãããã®ã¡ãœãããã€ã³ã¿ãŒã»ããããŸãã
ãµãŒãã¹ã¬ãã«
ãã¡ã€ã³åºæã®èšèšã§ã¯ããã¡ã€ã³ãµãŒãã¹ã䜿çšããŠãã¡ã€ã³ããžãã¯ãå®è£ ãããªããžããªã䜿çšããŠããŒã¿ããŒã¹ã¿ã¹ã¯ãå®è¡ã§ããŸãã ããšãã°ãPersonServiceã®å®çŸ©ã¯æ¬¡ã®ããã«ãªããŸãã
public class PersonService : IPersonService { private readonly IPersonRepository _personRepository; private readonly IPhoneRepository _phoneRepository; public PersonService(IPersonRepository personRepository, IPhoneRepository phoneRepository) { _personRepository = personRepository; _phoneRepository = phoneRepository; } public void CreatePerson(Person person) { _personRepository.Insert(person); } [UnitOfWork] public void DeletePerson(int personId) { _personRepository.Delete(personId); _phoneRepository.DeletePhonesOfPerson(personId); } //... some other methods are not shown here since it's not needed. See source codes. }
äžèšã§å®çŸ©ããUnitOfWorkå±æ§ã®äœ¿çšã«æ³šæããŠãã ããã DeletePersonã¡ãœããã¯UnitOfWorkãšããŠããŒã¯ãããŸãã 2ã€ã®ç°ãªããªããžããªã¡ãœãããåŒã³åºãããããã®ã¡ãœããåŒã³åºãã¯ãã©ã³ã¶ã¯ã·ã§ã³ã§ããå¿ èŠããããŸãã äžæ¹ãCreatePersonã¡ãœããã¯UnitOfWorkãšããŠããŒã¯ãããŸãããããã¯ãç¬èªã®ãã©ã³ã¶ã¯ã·ã§ã³ã管çã§ããå人ãªããžããªçšã®Insertã¡ãœããã1ã€ã ãåŒã³åºãããã§ãã ããã«ããããã©ã®ããã«å®è£ ãããããèŠãŠãããŸãã
äŸåæ§æ³šå ¥ïŒDIïŒ
Castle Windsorãªã©ã®DIã³ã³ããã¯ãã¢ããªã±ãŒã·ã§ã³ãªããžã§ã¯ãã®äŸåé¢ä¿ãšã©ã€ããµã€ã¯ã«ã管çããããã«äœ¿çšãããŸãã ããã«ãããççµåã®ã³ã³ããŒãã³ããšã¢ãžã¥ãŒã«ãã¢ããªã±ãŒã·ã§ã³ã«äœæã§ããŸãã ASP.NETã¢ããªã±ãŒã·ã§ã³ã§ã¯ãéåžžãDIã³ã³ããã¯global.asaxãã¡ã€ã«ã§åæåãããŸãã ããã¯éåžžãèµ·åæã«çºçããŸãã
public class MvcApplication : System.Web.HttpApplication { private WindsorContainer _windsorContainer; protected void Application_Start() { InitializeWindsor(); // Other startup logic... } protected void Application_End() { if (_windsorContainer != null) { _windsorContainer.Dispose(); } } private void InitializeWindsor() { _windsorContainer = new WindsorContainer(); _windsorContainer.Install(FromAssembly.This()); ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_windsorContainer.Kernel)); } }
WindsowContainerãªããžã§ã¯ãã¯ãäŸåé¢ä¿ãå®è£ ãããšãã«éèŠã§ãããã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«äœæãããæåŸã«åé€ãããŸãã äŸåé¢ä¿ãå®è£ ããã«ã¯ãInitializeWindsorã¡ãœããã§MVCã³ã³ãããŒã©ãŒãã¡ã¯ããªã®ããã©ã«ãèšå®ãå€æŽããå¿ èŠããããŸãã ASP.NETã®MVCãã¿ãŒã³ãïŒãã¹ãŠã®WebèŠæ±ã§ïŒã³ã³ãããŒã©ãŒãå¿ èŠãšãããšãã¯ãã€ã§ãã äŸåæ§æ³šå ¥ã䜿çšããŠäœæããŸãã ãã£ãã¹ã«ãŠã£ã³ã¶ãŒã®è©³çŽ°ã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã ã³ã³ãããŒã©ãã¡ã¯ããªã¯æ¬¡ã®ããã«ãªããŸãã
public class WindsorControllerFactory : DefaultControllerFactory { private readonly IKernel _kernel; public WindsorControllerFactory(IKernel kernel) { _kernel = kernel; } public override void ReleaseController(IController controller) { _kernel.ReleaseComponent(controller); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { if (controllerType == null) { throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path)); } return (IController)_kernel.Resolve(controllerType); } }
äžèŠããã ãã§ãéåžžã«ã·ã³ãã«ã§ç解ãããããã®ã§ãã PhoneBookDependencyInstallerã¯ã©ã¹ã䜿çšããŠãç¬èªã®ãªããžã§ã¯ãäŸåé¢ä¿ãåã蟌ãå¿ èŠããããŸãã Castle Windsorã¯ãIWindsorInstallerã®å®è£ ã«ããããã®ã¯ã©ã¹ãèªåçã«æ€åºããŸãã è¡_windsorContainer.InstallïŒFromAssembly.ThisïŒïŒïŒ;ãèŠããŠãããŠãã ããã global.asaxãã¡ã€ã«å ã
public class PhoneBookDependencyInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Kernel.ComponentRegistered += Kernel_ComponentRegistered; //Register all controllers container.Register( //Nhibernate session factory Component.For<ISessionFactory>().UsingFactoryMethod(CreateNhSessionFactory).LifeStyle.Singleton, //Unitofwork interceptor Component.For<NhUnitOfWorkInterceptor>().LifeStyle.Transient, //All repoistories Classes.FromAssembly(Assembly.GetAssembly(typeof(NhPersonRepository))).InSameNamespaceAs<NhPersonRepository>().WithService.DefaultInterfaces().LifestyleTransient(), //All services Classes.FromAssembly(Assembly.GetAssembly(typeof(PersonService))).InSameNamespaceAs<PersonService>().WithService.DefaultInterfaces().LifestyleTransient(), //All MVC controllers Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient() ); } /// <summary> /// Creates NHibernate Session Factory. /// </summary> /// <returns>NHibernate Session Factory</returns> private static ISessionFactory CreateNhSessionFactory() { var connStr = ConfigurationManager.ConnectionStrings["PhoneBook"].ConnectionString; return Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connStr)) .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetAssembly(typeof(PersonMap)))) .BuildSessionFactory(); } void Kernel_ComponentRegistered(string key, Castle.MicroKernel.IHandler handler) { //Intercept all methods of all repositories. if (UnitOfWorkHelper.IsRepositoryClass(handler.ComponentModel.Implementation)) { handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(NhUnitOfWorkInterceptor))); } //Intercept all methods of classes those have at least one method that has UnitOfWork attribute. foreach (var method in handler.ComponentModel.Implementation.GetMethods()) { if (UnitOfWorkHelper.HasUnitOfWorkAttribute(method)) { handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(NhUnitOfWorkInterceptor))); return; } } } }
ã芧ã®ãšãããCastle Windsorã®Registerã¡ãœããã䜿çšããŠãã¹ãŠã®ã³ã³ããŒãã³ããç»é²ããŠããŸãã 泚ïŒãã¹ãŠã®ãªããžããªã¯ã©ã¹ã¯1è¡ã§ç»é²ãããŸãã ãµãŒãã¹ãšã³ã³ãããŒã©ãŒã«ã€ããŠãåãããšãå¿ èŠã§ãã ãã¡ã¯ããªã¡ãœããã䜿çšããŠãNHibernateã§äœ¿çšããISessionãªããžã§ã¯ãïŒããŒã¿ããŒã¹æ¥ç¶ïŒãäœæããISessionFactoryãã¡ã¯ããªãäœæããŸãã Installã¡ãœããã®éå§æã«ãComponentRegisteredã€ãã³ãããã°ã«èšé²ããŠã€ã³ã¿ãŒã»ããããžãã¯ãå®è£ ããŸãã Kernel_ComponentRegisteredãèŠãŠãã ããã ã¡ãœããããªããžããªã¡ãœããã§ããå Žåãåžžã«ã€ã³ã¿ãŒã»ããã䜿çšããŸãã ããã«ãã¡ãœãããUnitOfWorkå±æ§ã§ããŒã¯ãããŠããå ŽåãNhUnitOfWorkInterceptorã¯ã©ã¹ã«ãã£ãŠãã€ã³ã¿ãŒã»ãããããŸãã
åå
ã€ã³ã¿ãŒã»ããã¯ãã¡ãœããåŒã³åºãã®éå§æãšçµäºæã«ããã€ãã®ã³ãŒããå®è¡ã§ããç¹å¥ãªææ³ã§ãã éåžžãã€ã³ã¿ãŒã»ããã¯ãã®ã³ã°ããããã¡ã€ãªã³ã°ããã£ãã·ã¥ãªã©ã«äœ¿çšãããŸãã ã¡ãœããèªäœãå€æŽããã«ãå¿ èŠãªã¡ãœããã«ã³ãŒããåçã«åã蟌ãããšãã§ããŸãã
ãã®å Žåãã€ã³ã¿ãŒã»ããã¯äœæ¥ãŠãããã®å®è£ ã«åœ¹ç«ã¡ãŸãã ç¹å®ã®ã¡ãœããããªããžããªã¡ãœããã§ããããUnitOfWorkå±æ§ãšããŠããŒã¯ãããŠããå ŽåïŒäžèšãåç §ïŒãããŒã¿ããŒã¹ãšïŒNHibernateã®ã»ãã·ã§ã³ïŒãžã®æ¥ç¶ãéããã¡ãœããã®éå§æã«ãã©ã³ã¶ã¯ã·ã§ã³ãéå§ããŸãã ã€ã³ã¿ãŒã»ãããããã¡ãœãããåäžã®äŸå€ãã¹ããŒããªãå Žåããã©ã³ã¶ã¯ã·ã§ã³ã¯ã¡ãœããã®æåŸã«ã³ããããããŸãã ã¡ãœãããäŸå€ãã¹ããŒãããšããã©ã³ã¶ã¯ã·ã§ã³å šäœãããŒã«ããã¯ãããŸãã NhUnitOfWorkInterceptorã¯ã©ã¹ã®å®è£ ãèŠãŠã¿ãŸãããã
/// <summary> /// This interceptor is used to manage transactions. /// </summary> public class NhUnitOfWorkInterceptor : IInterceptor { private readonly ISessionFactory _sessionFactory; /// <summary> /// Creates a new NhUnitOfWorkInterceptor object. /// </summary> /// <param name="sessionFactory">Nhibernate session factory.</param> public NhUnitOfWorkInterceptor(ISessionFactory sessionFactory) { _sessionFactory = sessionFactory; } /// <summary> /// Intercepts a method. /// </summary> /// <param name="invocation">Method invocation arguments</param> public void Intercept(IInvocation invocation) { //If there is a running transaction, just run the method if (NhUnitOfWork.Current != null || !RequiresDbConnection(invocation.MethodInvocationTarget)) { invocation.Proceed(); return; } try { NhUnitOfWork.Current = new NhUnitOfWork(_sessionFactory); NhUnitOfWork.Current.BeginTransaction(); try { invocation.Proceed(); NhUnitOfWork.Current.Commit(); } catch { try { NhUnitOfWork.Current.Rollback(); } catch { } throw; } } finally { NhUnitOfWork.Current = null; } } private static bool RequiresDbConnection(MethodInfo methodInfo) { if (UnitOfWorkHelper.HasUnitOfWorkAttribute(methodInfo)) { return true; } if (UnitOfWorkHelper.IsRepositoryMethod(methodInfo)) { return true; } return false; } }
ã€ã³ã¿ãŒã»ãããäž»ãªæ¹æ³ã§ãã ãŸããç¹å®ã®ã¹ã¬ããã«å¯ŸããŠä»¥åã«å®è¡ãããŠãããã©ã³ã¶ã¯ã·ã§ã³ãååšãããã©ããã確èªããŸãã ãã®å Žåãæ°ãããã©ã³ã¶ã¯ã·ã§ã³ã¯éå§ãããŸããããçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã䜿çšãããŸãïŒNhUnitOfWork.Currentãåç §ïŒã ãããã£ãŠãUnitOfWorkå±æ§ãæã€ãã¹ããããã¡ãœããåŒã³åºãã¯ãåããã©ã³ã¶ã¯ã·ã§ã³ãå ±æã§ããŸãã ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãäœæ¥åäœã¡ãœãããåããŠäœ¿çšãããšãã«ã®ã¿äœæãŸãã¯ã³ããããããŸãã ããã«ãã¡ãœããããã©ã³ã¶ã¯ã·ã§ã³ã«å¯Ÿå¿ããŠããªãå Žåãã¡ãœãããåŒã³åºããŠæ»ããŸãã invocation.ProceedïŒïŒã³ãã³ãã¯ãã€ã³ã¿ãŒã»ãããããã¡ãœãããåŒã³åºããŸãã
çŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ããªãå Žåã¯ãæ°ãããã©ã³ã¶ã¯ã·ã§ã³ãéå§ãããšã©ãŒããªãå Žåã¯ã³ãããããå¿ èŠããããŸãã ãã以å€ã®å Žåã¯ãããŒã«ããã¯ããŸãã ãã®åŸãNhUnitOfWork.Current = nullãèšå®ããŠãåŸã§å¿ èŠã«å¿ããŠãã®ã¹ããªãŒã ã®ä»ã®ãã©ã³ã¶ã¯ã·ã§ã³ãéå§ã§ããããã«ããŸãã UnitOfWorkHelperã¯ã©ã¹ãã芧ãã ããã
ãããã£ãŠãæ¥ç¶ãéãããéãããããã©ã³ã¶ã¯ã·ã§ã³ãéå§ãã³ããããããã³ããŒã«ããã¯ãããããããã®ã³ãŒãã¯ãã¢ããªã±ãŒã·ã§ã³ã®1ã€ã®ãã€ã³ãã§ã®ã¿å®çŸ©ãããŸãã