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