2010-03-16 4 views
6

J'apprends juste ASP.NET C# et essaye d'incorporer les meilleures pratiques dans mes applications. Tout ce que je lis dit de superposer mes applications en DAL, BLL, UI, etc. en fonction de la séparation des préoccupations. Au lieu de faire circuler des données, je pense à utiliser des objets personnalisés pour que je sois faiblement couplé à ma couche de données et que je puisse tirer parti d'intellisense dans VS. Je suppose que ces objets seraient considérés comme des DTO?Comment remplir une liste générique d'objets en C# à partir de la base de données SQL

D'abord, où ces objets résident-ils dans mes couches? BLL, DAL, autre? Deuxièmement, lorsque vous remplissez à partir de SQL, dois-je faire défiler un lecteur de données pour remplir la liste ou remplir d'abord une table de données, puis parcourir la table pour remplir la liste? Je sais que vous devez fermer la connexion à la base de données dès que possible, mais il semble que vous ayez besoin de plus de temps pour remplir la table de données, puis passer en boucle pour la liste. Troisièmement, tout ce que je vois ces jours-ci dit utiliser Linq2SQL. Je prévois d'apprendre Linq2SQL, mais en ce moment je travaille avec une base de données héritée qui n'a pas de configuration de clés étrangères et je n'ai pas la capacité de le réparer atm. Aussi, je veux en apprendre plus sur C# avant de commencer à entrer dans des solutions ORM comme nHibernate. Dans le même temps, je ne veux pas taper toute la connexion et la plomberie SQL pour chaque requête. Est-ce correct d'utiliser l'Enterprise DAAB pour l'instant?

Répondre

17

Vous avez beaucoup de questions dans une question. Linq2SQL est juste une sorte de ORM, si vous allez cette route, je regarderais le cadre d'entité (microsoft orm). Parlons un peu des applications en couches pour vous aider à comprendre comment peupler les objets. Votre application de base de données typique est composée de 3 couches (certaines disent 4 et se réfèrent à la base de données elle-même comme un calque, ce n'est vraiment pas grave). Vous avez les éléments suivants:

  • UI
  • BLL
  • DAL

Ainsi, votre communication est les pourparlers de l'interface utilisateur au BLL et les pourparlers BLL au DAL. La couche d'accès au client renvoie certaines données à la couche BLL qui, à son tour, la présente à l'interface utilisateur. Je ne sais pas qui vous a dit que les datasets/tables sont mauvais ... un lecteur est plus rapide mais ça ne veut pas dire que l'utilisation d'un datatable est mauvaise. Laissez-moi vous donner un exemple.

Arrêtez de penser à votre DAL comme une classe simple. Commencez à penser à la couche DAL en tant que dossier entier de différentes classes. L'une de ces classes est une classe DB statique. C'est statique parce que vous avez affaire à une base de données (dans la plupart des cas), donc pas besoin d'instancier la classe. Cela peut donc ressembler à ceci:

public static class DB { 
private static readonly string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString; 
private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory(dataProvider); 

public static int Update(string sql) 
     { 
      using (DbConnection connection = factory.CreateConnection()) 
      { 
       connection.ConnectionString = connectionString; 

       using (DbCommand command = factory.CreateCommand()) 
       { 
        command.Connection = connection; 
        command.CommandText = sql; 

        connection.Open(); 
        return command.ExecuteNonQuery(); 
       } 
      } 
     } 

public static DataTable GetDataTable(string sql) 
     { 
      using (DbConnection connection = factory.CreateConnection()) 
      { 
       connection.ConnectionString = connectionString; 

       using (DbCommand command = factory.CreateCommand()) 
       { 
        command.Connection = connection; 
        command.CommandType = CommandType.Text; 
        command.CommandText = sql; 

        using (DbDataAdapter adapter = factory.CreateDataAdapter()) 
        { 
         adapter.SelectCommand = command; 

         DataTable dt = new DataTable(); 
         adapter.Fill(dt); 

         return dt; 
        } 
       } 
      } 
} 

Une partie de ceci a été prise du site Web de dofactory. Grande ressource pour apprendre à utiliser les modèles de conception. De toute façon c'est juste un fichier .class. Maintenant vous en avez besoin d'un autre pour dire un CustomerDAO (un objet d'accès aux données client).

Ok, alors comment pouvez-vous utiliser cette classe de DB que vous avez créée (eh bien, j'utiliserais une combinaison de sprocs mais pour en faire un simple message, évitons les procédures stockées pour l'instant). Si j'ai besoin d'obtenir des clients, je pourrais définir ceci:

public IList<Customer> GetCustomers() 
{ 
    StringBuilder sql = new StringBuilder(); 
    sql.Append(" SELECT CustomerId, CompanyName, City, Country "); 
    sql.Append(" FROM Customer "); 

    DataTable dt = Db.GetDataTable(sql.ToString()); 

    return MakeCustomers(dt); 
} 

Rappelez-vous ceci est dans un fichier .class entièrement différent.Ok alors comment ne fait les clients recherchent:

private IList<Customer> MakeCustomers(DataTable dt) 
     { 
      IList<Customer> list = new List<Customer>(); 
      foreach (DataRow row in dt.Rows) 
       list.Add(MakeCustomer(row)); 

      return list; 
     } 

Alors ce que je fais ici est que j'avais un datatable plein de clients. Je dois faire une boucle à travers chaque ligne de la table de données et rendre le client:

private Customer MakeCustomer(DataRow row) 
     { 
      int customerId = int.Parse(row["CustomerId"].ToString()); 
      string company = row["CompanyName"].ToString(); 
      string city = row["City"].ToString(); 
      string country = row["Country"].ToString(); 

      return new Customer(customerId, company, city, country); 
     } 

donc ce client est new'd et stockée dans une liste de clients.

Ceci est juste un petit exemple de ce que fait votre couche d'accès aux données. La classe de base de données stocke simplement la chaîne de connexion et fonctionne pour obtenir un ensemble de données ou obtenir une table de données ou même dans votre cas obtenir un lecteur de données (que vous pourriez faire aussi). La classe CustomerDAO est simplement une classe qui traite des objets clients et peut implémenter une interface ICustomer.

Alors où est la classe Customer elle-même? Il peut s'agir d'un autre dossier en tant que couche de gestion, car il s'agit simplement d'un objet métier. Ici, vous pouvez définir des validations et des champs obligatoires dans la classe client.

Votre interface utilisateur n'a rien à voir avec les gestionnaires de données, les jeux de données ou le langage SQL. Votre couche Business n'a rien à voir non plus (elle définit certaines règles derrière vos objets métier). Votre dal peut être très flexible (peut travailler avec SQL, Oracle, etc) ou peut être limité à dire SQL Server si c'est ce que vous comptez faire. Ne surchargez pas votre application. Si vous êtes un utilisateur de MS et que vous êtes certain de n'utiliser que SQL Server, ne vous compliquez pas la tâche en essayant de déployer la DAL ultime qui fonctionne avec n'importe quel fournisseur. il est correct d'utiliser SQLCommand, SQLConnection, etc.

+0

Pourquoi ne pas combiner des clients, des clients et des clients en une seule méthode? – jpshook

+0

@developr - Alors vous auriez une grande fonction laide. Vous devez séparer les préoccupations afin de ne pas compliquer une fonction. Une fonction devrait simplement faire * un * travail/tâche. Si je mettais tout en un, vous obtiendriez des clients, en plus d'aller chercher/boucler les clients, en plus de rajouter un client en allouant de l'espace, en affectant des valeurs à l'objet client et enfin en ajoutant le client à la liste. Vous pourriez tout faire en un, mais cela complique votre fonction. La lisibilité est beaucoup plus simple dans mon exemple. – JonH

+0

Comment ajouter des paramètres à la méthode Update dans la classe DB correctement? Je ne suppose pas, vous feriez comme: DB.Update ("mettre à jour le jeu de table nom d'utilisateur = '" + varusername + "' WHERE x =" + varx + "); ... alors vous passeriez le long d'une SqlCommand avec les paramètres ou le dictionnaire ou la liste Key/Value et construisez la sqlcommand dans la méthode Update.Je pense que l'utilisabilité de la méthode est supposée être aussi large/générale que possible – Jesper

0

Allez voir l'ORM OpenAccess de Telerik. Vous n'avez pas besoin de l'utiliser comme un "ORM" mais cela vous donnera la possibilité de générer rapidement des classes pour vos tables sans avoir à tout taper. Vous pouvez ensuite utiliser ces classes à typage fort dans votre couche d'accès au client pour tout ce que vous voulez, qu'il s'agisse d'une écriture personnalisée ou d'un modèle ORM avec quelque chose d'autre. Dans ce cas, vous l'utilisez simplement pour la génération de code afin de vous lancer rapidement (et ces objets sont très basiques et simples - c'est-à-dire exactement où vous commenceriez si vous deviez les écrire à la main).

En ce qui concerne l'abstraction de vos objets DAL à partir de vos autres objets, allez voir WCF. Vous pouvez le mettre entre chaque couche (UI/Biz/DAL) et il va générer des objets proxy qui prendront soin de votre séparation des préoccupations.

Questions connexes