0

Ich habe einen Windows-Dienst implementiert, der eine Liste von E-Mails aus der Datenbank erhalten und sie alle 60 Sekunden mit .net-Mail senden soll. Ich habe es mit Repository-Muster entworfen, siehe den Screenshot der Lösung Ordner und Projekte. Click to see the pictureEF6 Repository-Muster in Windows-Dienst

Fragen:

  1. In Bezug auf das Muster bin ich auf dem richtigen Weg? Struktur der getrennten Projekte, Erstellen einer Schnittstelle für jedes Repository und eines Service pro Repository.
  2. Wenn einige der Geschäftslogiken nichts mit der Datenbank zu tun haben, muss ich noch ein Repository für sie erstellen oder ein Service ist genug?
  3. Ich habe eine SMTP-Dienstklasse, die .net Mail und Senden von E-Mails implementiert, während ich jede E-Mail senden ich die Datenbank aktualisieren möchte, würde ich gerne wissen, ob die Update-Logik in der SMTP-Dienst-Klasse ist eine gute Praxis? Es ist so etwas wie unten

    public class SMTPService : ISMTPService 
        { 
    
         SmtpClient client; 
         MailMessage newMessage; 
         EmailService emailService; 
         IEventLoggerService MailCheckerLog; 
    
         public async Task SendEmail(tb_Email email) 
         {...} 
    
         void SendCompletedCallback(object sender, System.ComponentModel.AsyncCompletedEventArgs e, tb_Email email) 
         { 
    
          if (e.Cancelled) 
          { 
    
          } 
          if (e.Error != null) 
          { 
    
          } 
          else 
          { 
           email.DateSent = DateTime.Now; 
           emailService.Update(email); 
          } 
    
          client.Dispose(); 
          newMessage.Dispose(); 
    
         } 
    

    }

Antwort

0

Ich bin nicht sicher, was Sie genau erreichen möchten und welche geschäftlichen Anforderungen Sie haben.

Die Struktur ist vorerst in Ordnung, aber bedenken Sie Folgendes: Sie haben eine Benutzerentität und eine Fotoentität. Jedem Benutzer muss ein Foto zugeordnet sein. Wie würdest du mit diesem Szenario umgehen?

Sie müssen ein UserRepository und ein PhotoRepository erstellen. Natürlich müssen Sie zuerst den Benutzerdatensatz einfügen, damit der Fotoeintrag später darauf verweist. So rufen Sie die Insert() - Methode des UserRepository auf. Wenn der Benutzer eingefügt wird, rufen Sie die Insert() - Methode des PhotoRepository auf. Was aber, wenn Insert() fehlschlägt? Jetzt haben Sie einen Benutzer in der Datenbank, der kein Foto hat.

Sie müssen den Benutzer und das Foto zusammen in einer Transaktion einfügen. Hier kommt das Arbeitseinheitsmuster ins Spiel. Sie müssen das verwenden, wenn Sie eine Geschäftslogik haben, die mehr als einen Entitätstyp betrifft. Wenn Sie nur E-Mails bearbeiten, ist das in Ordnung. Wenn nicht, müssen Sie dieses Muster zu Ihrer Anwendung hinzufügen. Siehe ein Beispiel here.

Ein Service ist wiederum etwas, das Geschäftstransaktionen abwickelt, und eine Geschäftstransaktion kann mehrere Arten von Entitäten berühren. Auch hier kann Ihnen das Muster der Arbeitseinheit helfen. In der Regel werden jedoch Repositorys basierend auf Ihren Berechtigungen und Diensten basierend auf Ihrer Geschäftslogik erstellt. In dem Beispiel könnten Sie einen UserService haben, der sowohl das UserRepository als auch das PhotoRepository verwendet (normalerweise über die Arbeitseinheit).

Im Falle des Sendens der E-Mails, würde ich wieder die Dienste basierend auf meiner Geschäftslogik entwerfen. Und wahrscheinlich ist die Geschäftslogik "E-Mails senden", nicht "E-Mails per SMTP versenden". Was passiert, wenn Sie sich für einen Dienst wie SendGrid entscheiden? Dann ist es nicht mehr SMTPService.

Ich würde wahrscheinlich einen EmailService erstellen (den Sie auch haben), und dies hätte eine SendEmails() -Methode. Dies würde das EmailRepository verwenden, um die E-Mails abzurufen, sie über SMTP zu senden, sie dann zu aktualisieren und über die Arbeitseinheit zu speichern.

Oder, wenn Sie wirklich abstrakt sein möchten, können Sie eine IEmailSenderService-Schnittstelle mit einer Methode, SendEmail (E-Mail-E-Mail) erstellen.Anschließend können Sie einen SmtpEmailSenderService erstellen, der diese Schnittstelle implementiert und die SmtpClient-Klasse umschließt und die E-Mail über SMTP sendet. Wenn Sie sich entscheiden, zu SendGrid zu wechseln, können Sie einen SendGridEmailSenderService erstellen, der mithilfe von HttpClient Anforderungen an SendGrid absetzt. Das Update wird immer noch im EmailService mit dem Repository und der Arbeitseinheit durchgeführt, aber jetzt verwendet der EmailService selbst nicht SmtpClient, sondern einfach die IEmailSenderService-Schnittstelle.

+0

Danke für Ihre Antwort, ich habe nur eine Einheit, die E-Mails ist. Brauche ich noch UOW? Wie ich hörte, ist das nützlich, wenn wir mehr als eine Entität haben. – user65248

+0

Wenn Sie nur eine Entität haben, brauchen Sie die UOW nicht. –

+0

Aus Neugierde benutze ich momentan SendMailAsync, um E-Mails zu senden und das Datenbank-Update zu verarbeiten, wenn das SendComplete-Ereignis ausgelöst wird. Da ich mehr als 100 E-Mails in einem Batch sende, wird manchmal SendComplete nicht ausgelöst, bevor die nächste E-Mail verarbeitet wird. Deshalb verwende ich für jede Transaktion einen neuen dbco0ntext, indem ich meine update-Methode in eine using-Anweisung von dbcontext einpacke. wie unten unter Verwendung von (BBEntities db = new BBEntities()) { db.Entry (obj) .State = EntityState.Modified; db.SaveChanges(); } – user65248