简体   繁体   English

C#EF +存储库+ UnitOfWorkk模式

[英]C# EF + Repository + UnitOfWorkk pattern

I have a question about architecture , this is my scenario, I am building a layered solution using EF , so I did Repositories for my entities and UnitOfWork to manage my repositories is perfect I put control methods and transaction works , my bussiness entity consumes the unit of work , and I get to work with my business rules , but I have a problem, for example , there is a method I need to use two methods of business to avoid code repetition and work in the same transaction How can I do this ? 我有一个关于体系结构的问题,这是我的情况,我正在使用EF构建分层解决方案,所以我为实体和RestrictionOfWork做了存储库来管理我的存储库是完美的,我放置了控制方法和事务工作,我的业务实体消耗了该单元工作,我可以使用我的业务规则,但是有一个问题,例如,有一种方法我需要使用两种业务方法来避免代码重复并在同一事务中工作我该怎么做?

Bussiness methods below: 业务方法如下:

    public void LinkCard(int cardId, long pin) 
    {
        if (cardId < 1 || pin < 1)
            throw new ArgumentException("Invalid parameters!");

        using (UnitOfWorkBol uowb = new UnitOfWorkBol(Log))
        {
            try
            {
                Card card;
                bool success = true;
                Pin pinResult;

                if(!Validator.UseRelesead(cardId, out card, uowb))
                    throw new CardException("La tarjeta no liberado para su uso!");

                pinResult = uowb.RepositoryPin.LoadPinByPin(pin);

                if(!Validator.UseRelesead(pinResult))
                    throw new CardException("La cuenta no está aprobado para su uso!");

                //se não existir cadastra o novo cartão caso contrário só vincula
                if (card == null)
                {
                    card = new Card
                            {
                                CARD_ID = cardId,
                                DISABLED = false,
                                pin = pinResult
                            };

                    success = uowb.GetBaseRepository<Card>().Add(card);
                }
                else 
                { 
                    card.pin = pinResult;
                    success = uowb.RepositoryCard.Update(card);
                }

                if (success)
                    uowb.SaveChanges();

            }
            catch (Exception ex)
            {
                Log.MostraMensagem(LogClass.MsgType.Error, 0, "LinkCard()" + ": " + ex.Message);
                throw;
            }
        }    
    }

    public void CancelCard(int cardId, int reasonId, long Epin) 
    {
        if (cardId < 1)
            throw new ArgumentException("Invalid parameter", "cardId");

        using(UnitOfWorkBol uowb = new UnitOfWorkBol(Log))
        {
            try
            {

                if (Validator.IsCancelled(cardId, uowb))
                    throw new CardException("La tarjeta ya se cancela!");

                Card card = uowb.GetBaseRepository<Card>().LoadById<int>(cardId);

                if (card == null)
                    throw new CardException("Tarjeta no encontrada!");

                //adiciona o cartão na tabela de cancelamento e o desativa
                CancelCard cancel = new CancelCard()
                {
                    card = card,
                    cashier_hist = uowb.RepositoryCashierHist.LoadCurrentCashierHist(Epin),
                    DATE = DateTime.Now,
                    reason_of_cancel = uowb.GetBaseRepository<ReasonOfCancel>().LoadById<int>(reasonId)
                };

                card.DISABLED = true;
                card.pin = null;

                bool success = uowb.GetBaseRepository<CancelCard>().Add(cancel);

                if (success)
                    success = uowb.GetBaseRepository<Card>().Update(card);

                if (success)
                    uowb.SaveChanges();
            }
            catch (Exception ex)
            {
                Log.MostraMensagem(LogClass.MsgType.Error, 0, "CancelCard()" + ": " + ex.Message);
                throw;
            }
        }
    }

i need call these methods in one on the transaction, thanks! 我需要在交易中一次调用这些方法,谢谢!

guys, i used transactionScope and works fine, but i dont like this solution because i am opening many transactions the code below: 伙计们,我使用了transactionScope并可以正常工作,但是我不喜欢这种解决方案,因为我在下面的代码中打开了很多事务:

   public void CancelAndLinkCard(CancelAndTransferDTO dto) 
    {
        using (TransactionScope scope = new TransactionScope()) 
        {
            CancelCard(dto.OldCardId, dto.ReasonId, dto.Epin);
            LinkCard(dto.NewCardId, dto.Pin);
            scope.Complete();
        }
    }

maybe to use a facade pattern and the view access the facade and this to control the transaction is better but i dont know i need help thanks by replies 也许使用外观模式和视图访问外观,这可以更好地控制交易,但我不知道我需要帮助,谢谢

If you are disposing of the context in both methods, I really don't see a way to make it happen. 如果您要同时使用两种方法处理上下文,那么我真的看不到实现它的方法。 I will probably just write another method that does both things. 我可能只会写另一种同时做这两种事情的方法。

If both of these methods are in the same class you could assign the dbContext to a private property and use it instead of creating a new dbContext for each of the methods (And take out your Using statements because otherwise it will dispose of the context when it leaves them). 如果这两个方法都在同一个类中,则可以将dbContext分配给私有属性,然后使用它,而不是为每个方法创建一个新的dbContext(并取出您的Using语句,因为否则它将在处理该上下文时丢弃该上下文离开他们)。

However, I agree with Gert above - the structure of your solution is what is making this hard for you. 但是,我同意上述Gert的观点-解决方案的结构使您难以承受。 DbContext IS a Unit of Work repository and should be treated as such. DbContext是工作单元存储库,应这样对待。 When we make repositories of repositories it just becomes turtles all the way down and madness comes of that. 当我们制作存储库时,它就一直变成乌龟,并因此而疯狂。

我理解您的观点,所以如果您有一个很好的例子,我如何对Gert说,这将是一个很好的帮助,也许这些添加,删除的部分应该位于存储库中,这样我就可以重复使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM