2011-01-08 16 views
1

Ich habe eine etablierte SQL Server-Datenbank eingerichtet. Ich habe dann ein Entity Framework-Modell in einer Konsolenanwendung generiert, um etwas Auswahl, Bearbeitung und Hinzufügen zur Datenbank zu testen. Alles ist gut gegangen.Entity Framework auf verschiedenen Projekten - sparen?

Ich bin jetzt mehr in Richtung meiner endgültigen physischen Gestaltung meiner WinForms und WebApp. Also habe ich beschlossen, das Projekt in separaten Projekten zu machen. Ich habe das Entity Framework in ein Data-Projekt verschoben, ein Services-Projekt erstellt und meine Konsolen-App immer noch als Testanwendung (alles in derselben Lösung).

Ich habe eine ClassLib mit Datenübertragungsobjekten, die zwischen meinen Layern übergeben werden. Meine GUI-Ebene und meine Service-Ebene kennen also das Entity Framework nicht. Ich habe Helfermethoden in meinem EF Projekt, das die EF-Daten in Liste usw. konvertieren ...

Eg einer Hilfsmethode:

using ClassLib; 

namespace Data 
{ 
    public class PayeeDAL : EntityBase 
    { 

    public static List<PayeeDto> GetPayees() 
    { 
     var payees = (from payee in Db.payees 
         select payee).ToList(); 

     List<PayeeDto> reply = new List<PayeeDto>(); 

     foreach (var pa in payees) 
     { 
      PayeeDto p = new PayeeDto 
          { 
           PayeeId = pa.payee_id, 
           Name = pa.name, 
           Deleted = pa.deleted == null 
          }; 
      reply.Add(p); 
     } 
     return reply; 

    } 
} 
} 

Und mein Datentransferobjekt sieht wie folgt aus:

namespace ClassLib 
{ 
    public class PayeeDto 
    { 
     public int PayeeId { get; set; } 
     public string Name { get; set; } 
     public bool Deleted { get; set; } 
    } 
} 

Also, meine Auswahl funktioniert gut mit diesem Design ... aber ... habe keine Ahnung, wie mit dem Speichern umzugehen.

In meiner Konsolenanwendung, wenn die EF mir zur Verfügung stand, habe ich dies:

     db.AddToaccount_transaction(ac); 

        account_transaction_line atl = new account_transaction_line 
        { 
         amount = amount, 
         cost_centre = 
          db.cost_centre.FirstOrDefault(
           cc => cc.cost_centre_id == costcentreid), 
         sub_category = 
          db.sub_category.First(
           sc => sc.sub_category_id == subcategoryId), 
         account_transaction = ac, 
         budget = db.budgets.FirstOrDefault(b => b.budget_id == budgetid) 

        }; 

        db.AddToaccount_transaction_line(atl); 


       } 



       db.SaveChanges(); 

Aber jetzt habe ich keinen Zugriff auf .AddTo .... und .SaveChanges ... In Meine Konsolen-App, ich würde ein übergeordnetes Objekt erstellen und dann ein paar untergeordnete Objekte hinzufügen ... und dann die untergeordneten Objekte zum übergeordneten Objekt hinzufügen und speichern.

Aber wie würde dies in meiner neuen Struktur getan werden? Ich denke, ich würde eine Save-Methode in jeder meiner Hilfsklassen haben ... Und dann eine Liste <> der untergeordneten Objekte, zusammen mit einer einzigen übergeordneten Klasse auf die Speichermethode übergeben ... und dann die Dtos umwandeln zu EF-Modellen, und speichern Sie es dann auf diese Weise?

Ist das ein akzeptabler Plan?

Antwort

3

Ich verwende nur DTO-Objekte, um Daten von A nach B zu übertragen. Das Aktualisieren, Hinzufügen, Entfernen usw., kapsle ich immer in Befehle (Befehlsmuster). Abrufen von Daten, die ich ähnlich mit "Helper" -Klassen.

Beispiel für Befehlsmuster:

Die Basisklassen:

namespace Busker.Data.Commands 
{ 
    /// <summary> 
    /// The 'Command' abstract class 
    /// </summary> 
    public abstract class Command 
    { 

     private string message = ""; 
     public string Message 
     { 
      get { return message; } 
      set { message = value; } 
     } 


     private bool success = false; 
     public bool Success 
     { 
      get { return success; } 
      set { success = value; } 
     } 

     private Validator validator = new Validator(); 
     public Validator Validator 
     { 
      get { return validator; } 
      set { validator = value; } 
     } 

     private CommandStatusCode statusCode = CommandStatusCode.OK; 
     public CommandStatusCode StatusCode 
     { 
      get { return statusCode; } 
      set { statusCode = value; } 
     } 

     public LoggingLevel LoggingLevel = LoggingLevel.Debug; 


     //public BuskerContext BuskerContext; 


     public bool IsValid() 
     { 
      if (validator.Errors.Count > 0) 
       return false; 
      return true; 

     } 

     public abstract void Execute(); 

     public void FailedSubCommand(Command cmd) 
     { 
      this.Success = cmd.Success; 
      this.Message = cmd.message; 
     } 
    } 
} 


namespace Busker.Data.Commands 
{ 
    public class Invoker 
    { 
     private Command command; 

     public Command Command 
     { 
      get { return command; } 
      set { command = value; } 
     } 


     public void SetCommand(Command command) 
     { 
      this.Command = command; 
     } 

     public virtual void ExecuteCommand() 
     { 
      if (command == null) 
       throw new Exception("You forgot to set the command!!"); 

      try 
      { 
       log(this.command.GetType().Name + " starting execution "); 
       command.Execute(); 
       if (!command.Success) 
       { 
        log(this.command.GetType().Name + " completed execution but failed. Message: " + command.Message + " " + command.StatusCode.ToString()); 
       } 
       else 
        log(this.command.GetType().Name + " completed execution. Success!"); 

      } 
      catch (Exception ex) 
      { 
       command.StatusCode = CommandStatusCode.Error; 
       Loggy.AddError("An unhandled error was caught in " + this.command.GetType().Name + ": " + ex.Message, ex); 
       command.Message = ex.ToString(); 
       //throw; 
      } 
     } 

     private void log(string msg) 
     { 
      switch (command.LoggingLevel) 
      { 
       case Busker.Data.Constants.LoggingLevel.Debug: 
        Loggy.Debug(msg); 
        break; 
       case Busker.Data.Constants.LoggingLevel.Off: 
        break; 
       default: 
        Loggy.Add(msg); 
        break; 

      } 

     } 

     public virtual void ExecuteLinqCommand() 
     { 
      this.ExecuteCommand(); 
     } 
    } 
} 

namespace Busker.Data.Commands 
{ 
    public static class Extensions 
    { 
     /// <summary> 
     /// Executes the command using the default invoker. 
     /// </summary> 
     /// <param name="aCommand"></param> 
     public static void Invoke(this Command aCommand) 
     { 
      System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace(); 
      System.Reflection.MethodBase m = stackTrace.GetFrame(1).GetMethod(); 
      String strMethodName = m.DeclaringType.Name + "." + m.Name; 

      try 
      { 
       Invoker invoker = new Invoker(); 
       invoker.SetCommand(aCommand); 
       invoker.ExecuteCommand(); 
      } 
      catch (Exception ex) 
      { 
       Loggy.AddError("An error occured in Extensions.Invoke. + " + strMethodName ,ex); 
       throw ex; 
      } 

     } 
} 

Implementierung Beispiel:

namespace Busker.Data.Commands.Message 
{ 
    public class CreateMessageCommand :Command 
    { 


     public CreateMessageCommand (int from, int to, string title, string body) 
     { 
       // set private variable.. 
     } 


     public override void Execute() 
     { 

      // Do your stuff here 


      be.SaveChanges(); 
      this.Success = true; 

     } 
    } 
} 

Verbrauch:

CreateMessageCommand cmd = new CreateMessageCommand (...); 
//Don't use the execute method of the command 
//the invoker, because implemented as an extension can be exchange in different 
//environments 
cmd.Invoke(); 
+0

Das wäre toll, wenn Sie zeigen coul ein Beispiel. Vielen Dank. – Craig

+0

bearbeitet meine Antwort, hoffe ich habe nichts vergessen .. – AyKarsi

+0

Ich bin nicht ganz verständnisvoll - also ich suchte mehr und stieß auf ein Tutorial, das eine Person zeigte, die eine EF-App, mit einer Konsolenanwendung. Sie referenzierte das EF-Projekt direkt aus der Konsolenanwendung. Das ist alles einfach, aber ... es scheint falsch. Sicherlich sollte es eine Service-Schicht geben und keine Interaktion zwischen dem GUI-Projekt und dem EF-Projekt, oder? – Craig

Verwandte Themen