📜 ⬆️ ⬇️

And how do you imagine a product?

Data, data, data ... I constantly have to work with them and, of course, I would like to have the most comfortable conditions for this.

Suppose we have a label in the database:
Product: id int - primary key, name varchar (256), description text, is_visible bit.

I would like to hear your views on how you will work with the data stored in it. Suppose you need to display a list of products (since I mostly work with Asp.net) on a web page.
')
But for starters, I will tell my version and, I hope, it will be useful to somebody.

Suppose that we considered the data from the database, but we need to store it somewhere. Certainly sdes should use a certain class:
  1. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  2. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  3. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  4. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  5. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  6. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  7. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  8. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  9. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  10. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  11. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  12. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  13. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }
  14. public class Product { private Product( int id, string name, string description, bool isActive) { ID = id; Name = name; Description = description; IsActive = isActive; } int ID { get ; private set ; } string Name { get ; set ; } string Description { get ; set ; } bool IsActive { get ; set ; } }

So, there is a class whose objects will be associated with the records in the Products table, but there is no possibility to somehow get objects containing real data.

Not a problem, add a static method that will return, for example, all the records from the table:
  1. public static List <Product> GetAll ()
  2. {
  3. // some actions are performed here
  4. }

It so happened that I chose to use as a List collection. But what does this method do?

There are a lot of options. The most obvious is to connect to the database, execute the query or stored procedure, and then put the data into the collection. This is not a very good way. It is possible that you will have to write similar methods that receive only visible elements or elements with a non-empty description.

For each method we will write the code to connect to the database? Of course not, just copy, then we will not notice a couple of nuances, and then, I think you guessed it ...

When I got a job as a programmer 10 months ago, I had to work with a ready-made online store engine. There, the methods for obtaining a collection of objects looked like this:
  1. public static ProductsCollection GetAll ()
  2. {
  3. // Get the table
  4. DataTable table = DBClass.GetTable (query, parameters);
  5. // Pass through the entire table, entering the data into the collection
  6. foreach (DataRow row in table.Rows)
  7. {
  8. result.Add (GetProductFromRow (row));
  9. }
  10. return result;
  11. }

The GetAll method itself is not connected in the database, the GetTable method does this, we just have to go through the table, transferring the data to the collection.

Convenient, not true? Unfortunately not, or rather convenient, but not as convenient as we would like.

First, there is a double copying of data (DB => DataTable => Collection), secondly, a pass through the table will also have to be written in each similar method, which is quite a routine exercise.

What would you like? About the following:
  1. public static List <Product> GetAll ()
  2. {
  3. return result;
  4. }

And it is quite possible. Just need a universal method for obtaining a collection of objects.

Since, depending on the objects with which this method will work, the result will be a collection of objects of this class, the method should be generalized.

What do you need to pass to the method? Firstly, the command and its type (sql-query or the name of hp), secondly, the parameters. Well and thirdly, since the method must know how to create objects, a certain delegate who will create an object.

Here's what I got:
  1. // Report on the last error that occurred
  2. public static string Error { get ; private set ; }
  3. // Database Connection String
  4. private static readonly string connectionString = "..."
  5. // The initial size of the collection when receiving multiple objects
  6. private const int itemsCount = 30;
  7. // Well, the method itself
  8. public static List <T> GetList <T> ( string commandText, CommandType commandType, DataReaderConstructor <T> dataReaderConstructor, params SqlParameter [] sqlParameters)
  9. where T: class
  10. {
  11. try
  12. {
  13. using ( var connection = new SqlConnection (connectionString))
  14. {
  15. var command = new SqlCommand (commandText, connection) {CommandType = commandType};
  16. if (sqlParameters! = null ) command.Parameters.AddRange (sqlParameters);
  17. connection.Open ();
  18. using ( var reader = command.ExecuteReader ())
  19. {
  20. if (reader == null ) return null ;
  21. var result = new List <T> (itemsCount);
  22. while (reader.Read ())
  23. {
  24. result.Add (dataReaderConstructor (reader));
  25. }
  26. return result;
  27. }
  28. }
  29. }
  30. catch (Exception exeption)
  31. {
  32. Error = exeption.Message;
  33. return null ;
  34. }
  35. }


All this is in a certain DBClass class, with the exception of the declaration of the delegate itself, which is somewhere nearby:
  1. public delegate T DataReaderConstructor <T> (IDataReader reader);

Now the list of products you can simply get say so:
  1. public static List <Product> GetAll ()
  2. {
  3. return DBClass.GetList ( "SGetProducts" , CommandType.StoredProcedure, Constructor)
  4. }

Before this, in the Product class, we declare:
  1. private static Product Constructor (IDataReader reader)
  2. {
  3. return new Product (( int ) reader [0], ( string ) reader [1], ( string ) reader [2], ( bool ) reader [3]);
  4. }


But at the beginning of the article I set the task to display a list of products, and in it, perhaps, the description is not used, only the ID and the name.

Create a new class, where there will be no description by analogy? What for? After all, we have anonymous types and we can get a collection of identifiers and names of visible products using anonymous types:
  1. const string query = "Select ID, Name from Product where is_visible" ;
  2. var products = DBClass.GetList (query, CommandType.Text,
  3. reader => new
  4. {
  5. ID = ( int ) reader [0],
  6. Name = ( string ) reader [1]
  7. });
* This source code was highlighted with Source Code Highlighter .


Well, actually, this is my version. Waiting for criticism, advice, suggestions, well, a little more criticism.
How do you prefer to work with data?

Source: https://habr.com/ru/post/42215/


All Articles