1

私はUnitOfWorkの新しいインスタンスを作成するusingステートメントを含むクラスのUpdateメソッドを持っています。これは電子メールを非同期的に送信していて、EFとDbContextはスレッドセーフではないからです各要求の新しいdbContext 私はUnitOfWorkでDI用にAutofacを使用しましたが、新しいインスタンスを作成するためにステートメントを使用する際に、新しいUnitOfWorkコンストラクタを使用する方法がわかりません。 これはコンソールアプリケーションであることに注意してください。 おかげAutofac DI inステートメントの使用

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 - > 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/ は、これは「通常の」の実装に比べて少し複雑ですが、非常にクリーン私の考えでは。自分のブログを宣伝するのではなく、postと書いて、この方法についてAutofacで実装する方法を説明しました。

この記事の最も重要なコードはこれです。

//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とRepoパターンで何が問題になっていますか? – user65248

+0

ありがとう、私はまだそれについて混乱している、記事を見て、それはまた別の方法はUoWファクトリを作成することですが、私の質問は私がUoWのコンストラクタに私のパラメータ(Autofac)新しいUoWFactoryインスタンスを作成します。私のUoWには、EventLoggerServiceである少なくとも1つの注入サービスが必要です。 – user65248

関連する問題