1

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

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(); 
      } 
     } 
} 

更新时间:

我得到了它与下面的解决方案但不知道这是否是最好的工作way

个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 - > Update方法

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

“ISMTPService”只是框架'SmtpClient'的包装?如果是这样,您应该知道即使使用异步方法也不能同时发送多个邮件,但代码必须等待每个电话/邮件完成才能开始新的邮件。总之,如果你想使用这个库,你最好使用同步方法。 – Igor

+0

是的,以及发送电子邮件和事件的方法。 – user65248

+0

但这正是我需要的,并且工作正常。代码发送电子邮件到服务器,然后它会引发事件,如果发送成功或不成功,并基于我使用更新方法来更新数据库。 – user65248

回答

0

虽然我不喜欢目前执行的UOW和存储库模式在你的榜样,我觉得你可以解决你的通过添加一个名为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(); 
     } 
    } 
} 

个人,我更德里克·格里尔的建议(该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; 
      } 
     } 
    } 
} 
+0

你能解释一下你的解决方案吗?另外UoW和回购模式有什么问题? – user65248

+0

谢谢,我仍然对此感到困惑,看到了这篇文章,并且还提到另一种方法是创建一个UoW工厂,我的问题是如何将我的参数(在Autofac中)传递给UoW构造函数,而我创建一个新的UoWFactory实例。我的UoW至少需要一个注入服务,即EventLoggerService。 – user65248