Правильно ли исполнены паттерны UnitOfWork и Repository для Nhibernate?

Изучал использования NHibernate и паттернов и в итоге пришел к такому коду, это тестовый набросок, хочу подобное использовать в одном солюшене в котором будут два проекта, один в виде сервисов, другой в виде ASP.NET MVC. Задаю вопрос с целью понять, правильно ли я понял эти паттерны, правильно ли их использовал и не лишние ли они вообще и можно было все не усложнять?
Исходный код (в виде одного файла, для запуска необходимы пакеты System.Data.SQLite, NHibernate, NHibernate.Mapping.Attributes):
spoiler
using System;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Mapping.Attributes;
using NHibernate.Tool.hbm2ddl;

namespace NhSQLiteTest
{
    [Class]
    [Serializable]
    public class Product
    {
        [Id(0, Name = "Id", Column = "Id", TypeType = typeof (int))]
        [Generator(0, Class = "identity")]
        public virtual int Id { get; set; }

        [Property]
        public virtual string Name { get; set; }
    }

    internal class Program
    {
        private static void Main()
        {
            using (var uow = new UnitOfWorkFactory().Create())
            {
                var productRepo = new Repository<Product>(uow);
                productRepo.SaveOrUpdate(new Product {Name = "TestRepo"});
            }
            Console.WriteLine("Success!");
            Console.ReadLine();
        }
    }

    public interface IUnitOfWorkFactory
    {
        IUnitOfWork Create();
    }

    public class UnitOfWorkFactory : IUnitOfWorkFactory
    {
        private ISessionFactory _sessionFactory;

        public ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }

        public IUnitOfWork Create()
        {
            return new UnitOfWork(SessionFactory.OpenSession());
        }

        private void BuildSessionFactory()
        {
            var config = new Configuration();

            config.Configure();
            config.AddAssembly(typeof (Product).Assembly);
            HbmSerializer.Default.Validate = true;
            var stream = HbmSerializer.Default.Serialize(typeof (Product).Assembly);
            stream.Position = 0;
            config.AddInputStream(stream);

            new SchemaUpdate(config).Execute(false, true);

            _sessionFactory = config.BuildSessionFactory();
            _sessionFactory.OpenSession();
        }
    }

    public interface IUnitOfWork : IDisposable
    {
    }

    internal class UnitOfWork : IUnitOfWork
    {
        public UnitOfWork(ISession session)
        {
            if (session == null) throw new ArgumentNullException(nameof(session));
            Session = session;
        }

        public ISession Session { get; private set; }

        public void Dispose()
        {
            Session.Dispose();
            Session = null;
        }
    }

    public interface IRepository<T> where T : class
    {
        void SaveOrUpdate(T obj);
    }

    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly UnitOfWork _uow;

        public Repository(IUnitOfWork uow)
        {
            if (uow == null) throw new ArgumentNullException(nameof(uow));
            _uow = uow as UnitOfWork;
            if (_uow == null)
            {
                throw new ArgumentException("Этот репозиторий принимает только единицу работы NHibernate");
            }
        }

        private ISession Session
        {
            get { return _uow.Session; }
        }

        public void SaveOrUpdate(T obj)
        {
            Session.SaveOrUpdate(obj);
        }
    }
}

  • Вопрос задан
  • 410 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы