Ich habe alle möglichen Beiträge zu diesem Thema gelesen, konnte aber keine Antwort auf meine Frage finden.

Der allgemeine Konsens ist, dass ich einen Kontext für 1 Arbeitseinheit (z. B. 1 Webseite) erstellen sollte. Ich habe jede Methode in meine Database.cs (siehe unten) mit 'using' eingeschlossen, was für mich bedeutet, dass jedes Mal, wenn eine Methode aus dieser Klasse aufgerufen wird, ein Kontext erstellt wird. Wenn ich also 2 Methoden aus Database.cs aus derselben Aktion in HomeController.cs aufrufen würde - würde das bedeuten, dass 2 Kontexte erstellt werden?

Wäre es nicht besser, ein privates Feld in Database.cs wie folgt zu deklarieren:

private Entities db = new Entities()

Und hat jede Methode in der Database.cs-Klasse Zugriff darauf? Welcher Ansatz ist der beste?

Meine aktuelle Implementierung (ich werde nur die Methode Verify einschließen, aber die Database-Klasse enthält viele Methoden):

HomeController.cs

    [AllowAnonymous]
    public class HomeController : Controller
    {
        private IDatabase Database;

        public HomeController()
        {
            this.Database = new Database();
        }

        [HttpGet]
        public ActionResult Verify(string id)
        {
            if (Database.VerifyUser(id))
            {
                return View();
            }
            else
            {
                ViewBag.Error = "There was an error with the verification process";
                return View();
            }
        }
    }

Database.cs

public class Database : IDatabase
{
... some other methods ...
    public bool VerifyUser(string verificationHash)
    {
        using (Entities db = new Entities())
        {
            var userToVerify = db.VerifyUser(verificationHash);
            int count = userToVerify.Count();
            if (count == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

Db.VerifyUser (..) - Dies ist ein Aufruf einer gespeicherten Prozedur

1
DeanR 3 Jän. 2016 im 12:48

2 Antworten

Beste Antwort

Ja, das bedeutet, dass es zwei Instanzen von DbContext gibt. Das Bessere ist, eine Instanz von DbContext in Ihrer Datenbankklasse zu haben und diese Instanz in all Ihren Methoden zu verwenden.

public class Database : IDatabase, IDisposeable
{
    private Entities db;
    public Database()
    {
        db = new Entities()
    }

... some other methods ...
    public bool VerifyUser(string verificationHash)
    {
        var userToVerify = db.VerifyUser(verificationHash);
        int count = userToVerify.Count();
        if (count == 1)
        {
            return true;
        }
        else
        {
            return false;
        }        
    }

    public void Dispose()
    {
        db.Dispose()
    }
}

Wenn Sie mit der Datenbankinstanz fertig sind, entsorgen Sie sie und der DbContext

public class HomeController : Controller
{
    private IDatabase Database;

    public HomeController()
    {
        this.Database = new Database();
    }

    [HttpGet]
    public ActionResult Verify(string id)
    {
        using(this.Database)
        {
            if (Database.VerifyUser(id))
            {
                return View();
            }
            else
            {
                ViewBag.Error = "There was an error with the verification process";
                return View();
            }
        }
    }   
}

Übrigens: Möglicherweise möchten Sie Ihre Ressourcen lieber auf Controller-Ebene entsorgen. In diesem Fall müssen Sie in Ihren Aktionen keine using-Anweisung hinzufügen, z. Fügen Sie dies Ihrem Controller hinzu:

protected override void Dispose(bool disposing)
{
    this.Database.Dispose();
    base.Dispose(disposing);
}
2
Wahid Bitar 3 Jän. 2016 im 10:18

Ja, in Ihrem Design wurde DbContext in jedem Methodenaufruf erstellt und entsorgt.

Tatsächlich ist es keine gute Lösung, alle Datenbankoperationen einer Klasse zuzuordnen und DbContext immer wieder zu erstellen. Sie haben wahrscheinlich in Zukunft ein Problem mit dieser Klasse. Es kann hundert Methoden in der Zeit haben und daher ist es schwierig zu warten und alle Entitäten sind nicht semantisch miteinander verbunden, was zu Verwirrung führen kann. Ich denke, es ist eine bessere Lösung, Entitätstypen in Klassen zu unterteilen. Sie haben beispielsweise Benutzer, Projekte und Abteilungen. Wenn wir meine Lösung auf diese Entitäten anwenden, sieht das uml-Klassendiagramm so aus.

Example Uml Design

Alle Repositorys verweisen auf DbContext. Es heißt Dependency Injection. Dies bedeutet, dass dbcontext einmal instanziiert wird und seine Referenz durch die erforderlichen Repositorys weiterleitet, sodass keine Neuerstellung des Kontexts erfolgt. Es gibt auch ein generisches Repository, in das Sie Standardverfahren einfügen können.

Sie können also solche Repositorys verwenden.

[HttpGet]
public ActionResult Verify(string id){

   using(var context = new DbContext())
   {
      var userRepo = new UserRepository(context); 
      //Department repository can be used over the same context.
      var departmentRepo = new DepartmentRepository(context);
      if(userRepo.verifyUser(id)){
         return View();
      }
   }

}
2
arnes 3 Jän. 2016 im 13:09