使用语句中的Autofac DI

时间:2017-08-23 10:18:47

标签: c# entity-framework dependency-injection console-application autofac

我的类中有一个Update方法,它包含一个using语句来创建UnitOfWork的新实例,这是因为我正在异步发送电子邮件,因为EF和DbContext不是线程安全的,必须为每个创建一个新的dbContext请求。 我在UnitOfWork中使用了Autofac for DI但是我不知道如何在using语句中使用我的新UnitOfWork构造函数来确保它创建一个新实例。 请注意,这是一个控制台应用程序。 感谢

UnitOfWork.cs

public class UnitOfWork : IUnitOfWork
{

    private IEventLoggerService MailCheckerLog;
    private readonly BBEntities ctx = new BBEntities();
    private IEmailRepository emailRepository;

    public UnitOfWork(IEventLoggerService MaLog, IEmailRepository emailRepo)
    {
        emailRepository = emailRepo;
        MailCheckerLog = MaLog;
    }

    public IEmailRepository EmailRepository
    {
        get
        {

            if (this.emailRepository == null)
            {
                this.emailRepository = new EmailRepository(ctx);
            }
            return emailRepository;
        }
    }

    public void Commit()
    {
        try
        {
            this.ctx.SaveChanges();
        }
        catch (Exception e)
        {
            MailCheckerLog.log("Unit Of Work Exception => Commit() => " + e.Message.ToString(), EventLogEntryType.Error);
        }
    }

}

EmailService.cs

    public class EmailService : IEmailService
    {

        private IUnitOfWork unitOfWork;
        private IEventLoggerService MailCheckerLog;
        private ISMTPService SMTPService;

        public EmailService(IEventLoggerService Log, IUnitOfWork uOfWork, ISMTPService SMTPS)
        {
            unitOfWork = uOfWork;
            MailCheckerLog = Log;
            SMTPService = SMTPS;
            SMTPService.OnMailSendComplete += new EventHandler(SendCompletedC);
        }




        public void Update(tb_Email obj)
        {
            IUnitOfWork unitOfWork2;
            using (unitOfWork2 = new UnitOfWork())
            {
                unitOfWork2.EmailRepository.Update(obj);
                unitOfWork2.Commit();
            }
        }
}

更新

我使用以下解决方案,但不确定它是否是最佳方式

UnitOfWorkFactory.cs

public class UnitOfWorkFacotry : IUnitOfWorkFactory
{

    private IUnitOfWork uow;
    private IEmailRepository emailrepo;
    private IEventLoggerService eventlog;

    public UnitOfWorkFacotry(IEventLoggerService MaLog, IEmailRepository emailRep)
    {

        emailrepo = emailRep;
        eventlog = MaLog;
    }

    public IUnitOfWork GetCurrent()
    {
        return uow ?? create();
    }

    public IUnitOfWork create()
    {
        return new UnitOfWork(eventlog, emailrepo);
    }

}

EmailService.cs - >更新方法

    public void Update(tb_Email obj)
    {
        IUnitOfWork unitOfWork2;
        using (unitOfWork2 = unitOfWorkFactory.create())
        {
            unitOfWork2.EmailRepository.Update(obj);
            unitOfWork2.Commit();
        }
    }

1 个答案:

答案 0 :(得分:0)

虽然我不喜欢您的示例中的UoW和Repository模式的当前实现,但我认为您可以通过添加名为BeginTransaction()的方法或类似方法来解决您的问题。

这样您就可以注入UnitOfWork并开始使用它。这也为您提供了何时启动事务以及在您的方法中添加一些额外逻辑的灵活性。

在您的情况下,我认为这应该类似于以下代码块。

public interface IUnitOfWork : IDispose
{
    void BeginTransaction();
    void Commit();
}


public class EmailService : IEmailService
{

    private IUnitOfWork unitOfWork;
    private IEventLoggerService MailCheckerLog;
    private ISMTPService SMTPService;

    public EmailService(... IUnitOfWork unitOfWork ..)
    {
        this.unitOfWork = unitOfWork;
        //Other stuff
    }

    public void Update(tb_Email obj)
    {
        IUnitOfWork unitOfWork2;
        using (unitOfWork2.BeginTransaction())
        {
            unitOfWork2.EmailRepository.Update(obj);
            unitOfWork2.Commit();
        }
    }
}

我个人更喜欢Derek Greer的建议(Unit of Work Decorator),他在这篇文章中解释得非常好:https://lostechies.com/derekgreer/2015/11/01/survey-of-entity-framework-unit-of-work-patterns/ 与“常规”相比,这有点复杂。实现,但在我看来更清洁。不是为了宣传我自己的博客,但我已经写了一篇关于如何使用Autofac实现的post

这篇文章最重要的代码就是这个。

//Registration
builder.RegisterGeneric(typeof(IncomingFileHandler<>)).Named("commandHandler", typeof(IIncomingFileHandler<>));
builder.RegisterGenericDecorator(typeof(IncomingFileHandlerTransactionDecorator<>), typeof(IIncomingFileHandler<>), fromKey: "commandHandler");

//The unit of work decorator
public class IncomingFileHandlerTransactionDecorator<TCommand> : IIncomingFileHandler<TCommand> 
    where TCommand : IncomingFileCommand
{
    private readonly IIncomingFileHandler<TCommand> decorated;
    private readonly IDbContext context;

    public IncomingFileHandlerTransactionDecorator(IIncomingFileHandler<TCommand> decorated, IDbContext context)
    {
        this.decorated = decorated;
        this.context = context;
    }

    public void Handle(TCommand command)
    {
        using (var transaction = context.BeginTransaction())
        {
            try
            {
                decorated.Handle(command)

                context.SaveChanges();
                context.Commit(transaction);
            }
            catch (Exception ex)
            {
                context.Rollback(transaction);
                throw;
            }
        }
    }
}