3 Stimmen

Wie kann ich meine Datenzugriffsklassen in ASP.NET verbessern?

Ich programmiere schon eine Weile, betrachte mich aber immer noch als Anfängerin. Ich verwende sehr einfache ADO.NET-Klassen mit eingebauten SQL-Anweisungen. Ich würde gerne von der Community erfahren, was ich falsch mache und wie ich mich verbessern kann, und was die vorgeschlagenen nächsten Schritte sind, um meine Kodierung an die aktuellen Standards anzupassen.

Ich bin wirklich daran interessiert, EF auszuprobieren, obwohl ich kein Tutorial finden kann, das zu meiner Art des BLL- und DAL-Unterrichts passt.

Grundsätzlich, wenn ich eine Gabe habe, würde ich eine Gabe-Klasse erstellen (BLL \Gift.cs ) :

using MyProject.DataAccessLayer;

namespace MyProject.BusinessLogicLayer
{
public class Gift
{

    public int GiftID { get; set; }
    public string GiftName { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }

    public static Gift GetGiftByID(int GiftID)
    {
        GiftDAL dataAccessLayer = new GiftDAL();
        return dataAccessLayer.GiftsSelectByID(GiftID);
    }

    public void DeleteGift(Gift myGift)
    {
        GiftDAL dataAccessLayer = new GiftDAL();
        dataAccessLayer.DeleteGift(myGift);
    }

    public bool UpdateGift(Gift myGift)
    {
        GiftDAL dataAccessLayer = new GiftDAL();
        return dataAccessLayer.UpdateGift(myGift);
    }

    public int InsertGift(string GiftName, string Description, decimal Price)
    {
        Gift myGift = new Gift();
        myGift.GiftName = GiftName;
        myGift.Description = Description;
        myGift.Price = Price;

        GiftDAL dataAccessLayer = new GiftDAL();
        return dataAccessLayer.InsertGift(myGift);
    }
}
}

Ich habe dann eine DAL-Klasse, die meine Verbindungszeichenfolge enthält (DAL \sqlDAL.css ) :

namespace MyProject.DataAccessLayer
{
public class SqlDataAccessLayer
{
    public readonly string _connectionString = string.Empty;

    public SqlDataAccessLayer()
    {
        _connectionString = WebConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString;
        if (string.IsNullOrEmpty(_connectionString))
        {
            throw new Exception("No database connection String found");
        }
    }
}
}

und dann eine DAL-Klasse (DAL \giftDAL.cs ), wo ich einige der Methoden (Aktualisieren und Löschen) gezeigt habe:

using MyProject.BusinessLogicLayer;

namespace MyProject.DataAccessLayer
{
public class GiftDAL : SqlDataAccessLayer
{
    public bool UpdateGift(Gift GifttoUpdate)
    {
        string UpdateString = "";
        UpdateString += "UPDATE Gifts SET";
        UpdateString += "GiftName = @GiftName";
        UpdateString += ",Description = @Description ";
        UpdateString += ",Price = @Price ";
        UpdateString += " WHERE GiftID = @GiftID";

        int RowsAffected = 0;

        try
        {
            using (SqlConnection con = new SqlConnection(_connectionString))
            {
                using (SqlCommand cmd = new SqlCommand(UpdateString, con))
                {
                    cmd.Parameters.AddWithValue("@GiftName", GifttoUpdate.GiftName);
                    cmd.Parameters.AddWithValue("@Description", GifttoUpdate.Description);
                    cmd.Parameters.AddWithValue("@Price ", GifttoUpdate.Price);
                    cmd.Parameters.AddWithValue("@GiftID", GifttoUpdate.GiftID);
                    con.Open();
                    RowsAffected = cmd.ExecuteNonQuery();
                }
            }
        }
        catch (Exception ex)
        {
            Utils.LogError(ex.Message, ex.InnerException == null ? "N/A" : ex.InnerException.Message, ex.StackTrace);
        }

        return (RowsAffected == 1);

    }

    public void DeleteGift(Gift GifttoDelete)
    {
        string DeleteString = "";
        DeleteString += "DELETE FROM GIFTS WHERE GIFTID = @GiftID";

        try
        {
            using (SqlConnection con = new SqlConnection(_connectionString))
            {
                using (SqlCommand cmd = new SqlCommand(DeleteString, con))
                {
                    cmd.Parameters.AddWithValue("@GiftID", GifttoDelete.GiftID);
                    con.Open();
                    cmd.ExecuteNonQuery();

                }
            }
        }
        catch (Exception ex)
        {
            Utils.LogError(ex.Message, ex.InnerException == null ? "N/A" : ex.InnerException.Message, ex.StackTrace);
        }
    }

}
}

Wie würden Sie mir also empfehlen, den Code zu verbessern (wenn ich weiterhin ADO.NET verwende) und was wäre mein nächster Schritt, um EF zu lernen - oder gibt es eine bessere Alternative?

Zum Wohl, Robbie

2voto

VinayC Punkte 44872

Wenn Sie bei ADD.NET bleiben wollen, dann schauen Sie sich doch mal Daten Anwendungsblock von Microsoft Enterprise Library (aktuelle Version ist 5.0 Mai 2011) - es erlaubt Ihnen, herstellerneutralen Code (MS-SQL/Oracle etc.) leicht zu schreiben und die meisten der Boiler-Plate-Codierung verpackt werden.

Diese ist wahrscheinlich die einfachste/kürzeste Anleitung, die ich finden konnte, um Ihnen den Einstieg zu erleichtern. Der MSDN-Link enthält jedoch zahlreiche Informationen und enthält Abschnitte mit Schlüsselszenarien, die den Einstieg erleichtern.

Ein weiterer Vorschlag ist die Verwendung von TransactionScope für die Verwaltung von Transaktionen (anstatt direkt mit dem DbTransaction-Objekt zu arbeiten).

Nach all dem empfehle ich die Verwendung von Entity Framework (oder einem ähnlichen OR-Mapper-Tool - z.B. NHibernet), weil Sie dann keinen typischen Code für grundlegende CRUD-Operationen schreiben müssen. Was Ihr Dilemma betrifft, so finden Sie hier einen grundlegenden Codeschnipsel für den Anfang - ich verwende EF 4.1 mit Code-First-Ansatz, POCO-Entitäten und Fluent API:

Entität:

public class Gift
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
}

Datenzugriffsschicht:

public class MyDbContext : DbContext
{
   public DbSet<Gift> Gifts { get; set; }

   public MyDbContext () : base("name=[ConnStringName]") {}

   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {
      // Fluent API to provide mapping - you may use attributes in entity class
      var giftConfig = modelBuilder.Entity<Gift>();
      giftConfig.Property(p => p.Id).HasColumnName("GiftID");
      giftConfig.Property(p => p.Name).HasColumnName("GiftName");
      giftConfig.Property(p => p.Description).HasColumnName("Description");
      giftConfig.Property(p => p.Price).HasColumnName("Price");
      giftConfig.HasKey(p => p.Id);

      base.OnModelCreating(modelBuilder); 
   }
}

Geschäftsebene:

public static class GiftManager
{
   public static Gift GetById(int id)
   {
      using(var db = new MyDbContext())
      {
         return db.Gifts.Find(id);
      }
   }

   public static void Add(Gift gift)
   {
      using(var db = new MyDbContext())
      {
         // do validation
         ...

         db.Gifts.Add(gift);

         // do auditing
         ...

         db.SaveChanges();
      }
   }

   public static void Update(Gift gift)
   {
      using(var db = new MyDbContext())
      {
         // do validation
         ...

         var entity = db.Sessions.Find(gift.Id);
         entity.Name = gift.Name;
         entity.Description = gift.Description;
         entity.Price = gift.Price;

         // do auditing
         ...

         db.SaveChanges();
      }
   }

}

2voto

Andre Loker Punkte 8288

Eine Sache, die (für mich) immer wichtig ist, ist wie testbar eine Klasse ist. Ich sehe eine Menge expliziter Objektkonstruktionen in Ihrem Code. Ihre Gift BL-Klasse hängt explizit von GiftDAL ab, was es sehr schwierig macht, die Gift-Klasse zu testen. Versuchen Sie, die Kopplung zwischen den Klassen zu reduzieren, indem Sie eine Abstraktion von GiftDAL erstellen (z. B. eine Schnittstelle) und diese Gift von außen zur Verfügung stellen ( Injektion von Abhängigkeiten ).

Ein großartiges Buch über gute Software-Design-Prinzipien ist Sauberer Code von Robert C. Martin . Er stellt die SOLID Grundsätze. Probieren Sie es aus!

Beachten Sie auch, dass Sie nun die Persistenz in Ihre Geschäftslogikklasse (oder Ihr Domänenmodell, wie es auch genannt wird) integrieren. Dies kann geschehen ( Aktiver Datensatz ), aber oft wird heutzutage ein anderer Ansatz gewählt, bei dem das Domänenmodell von der Infrastruktur getrennt wird. Der Grundgedanke ist: Die Tatsache, dass die Objekte irgendwie gespeichert werden müssen, ist wichtig, aber nicht wichtig für die Geschäftslogik selbst, so dass diese beiden Bereiche nach Möglichkeit getrennt werden sollten. Oft wird ein Objektrelationaler Mapper für .NET NHibernate o Entity Framework sind zwei Beispiele für OR-Mapper.

0voto

Induster Punkte 733

Ich habe eine Dal-Klasse, deren Methoden nur bindbare Objekte wie datatable, List, etc. zurückgeben. Nicht mehr und nicht weniger. Die gesamte Geschäftslogik findet dann natürlich im Code hinter einer Aspnet-Anwendung statt. Backing-Objekte zu erstellen ist in den meisten Fällen einfach zu viel Arbeit und ein Overkill. Ich bin mit Datentabellen und Listen vertraut.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X