Най-добри практики за внедряване на единица работа и модел на хранилище с помощта на ServiceStack.ORMLite

Да предположим, че има два интерфейса на хранилището:

interface IFooRepository
{
    void Delete(int id);
}

interface IBarRepository
{
    void Delete(int id);
}

И интерфейс на IUnitOfWork като:

interface IUnitOfWork : IDisposable
{
    void Commit();
    void Rollback();
}

какви са най-добрите практики за внедряване на тези интерфейси с помощта на ServiceStack.ORMLite, така че потребителят да може да ги използва като

MyFooRepository.Delete(4);
// if an Exception throws here, Bar won't be deleted
MyBarRepository.Delete(7);

Or

using (var uow = CreateUnitOfWork())
{
    MyFooRepository.Delete(4);
    MyBarRepository.Delete(7);
    uow.Commit();  //now they are in an transaction
}

person Sword-Breaker    schedule 20.02.2013    source източник
comment
Бих препоръчал да избягвате използването на UOW колкото е възможно повече. Прехвърлянето на отворена транзакция като това обикновено е много лош дизайн. (В по-ранни ревизии аз самият бях виновен за тези неща)   -  person Chris Marisic    schedule 08.09.2014


Отговори (1)


Не съм сигурен дали се нуждаете от Repository + UnitOfWork шаблони, но мисля, че има някои алтернативни решения в ServiceStack + OrmLite, които поддържат кода ви „СУХ“, преди да се наложи да въведете каквито и да е модели (особено ако търсите главно поддръжка за транзакции/връщане). Нещо като по-долу е мястото, откъдето бих започнал.

public class Foo //POCO for data access
{
    //Add Attributes for Ormlite
    public int Id { get; set;  }
}

public class Bar //POCO for data access
{
    //Add Attributes for Ormlite
    public int Id { get; set; }
}

//your request class which is passed to your service
public class DeleteById 
{
    public int Id { get; set; }
}

public class FooBarService : MyServiceBase //MyServiceBase has resusable method for handling transactions. 
{
    public object Post(DeleteById request)
    {
        DbExec(dbConn =>
                   {
                       dbConn.DeleteById<Foo>(request.Id);
                       dbConn.DeleteById<Bar>(request.Id);
                   });

        return null;
    }
}

public class MyServiceBase : Service
{
    public IDbConnectionFactory DbFactory { get; set; }

    protected void DbExec(Action<IDbConnection> actions)
    {
        using (var dbConn = DbFactory.OpenDbConnection())
        {
            using (var trans = dbConn.OpenTransaction())
            {
                try
                {
                    actions(dbConn);
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
        }
    }
} 

Някои препратки...

https://github.com/ServiceStack/ServiceStack.RedisWebServices – Горният код е модифициран от този пример

https://groups.google.com/forum/#!msg/servicestack/1pA41E33QII/R-trWwzYgjEJ - дискусия относно слоевете в ServiceStack

http://ayende.com/blog/3955/repository-is-the-new-singleton - Ayende Rahien (основен сътрудник на NHibernate) относно модел на хранилище

person paaschpa    schedule 20.02.2013
comment
В случай, че имате нужда от специална/сложна логика sql, къде бихте ги поставили? - person GorillaApe; 04.10.2013
comment
Предполагам, че можете да направите толкова специална/сложна логика sql, колкото искате в рамките на действието/функцията, изпратена до метода DbExec. Може също да напише самостоятелна функция и да я предаде (действието/функцията) в блока. Освен това този пример вероятно не е най-добрият подход за сложни ситуации. - person paaschpa; 04.10.2013